예제 #1
0
void GPUProgramManager::removeUnused() {
#ifdef C_CODE
  std::map<std::string, GPUProgram*>::iterator it = _programs.begin();
  while (it != _programs.end()) {
    if (it->second->getNReferences() == 0) {
      ILogger::instance()->logInfo("Deleting program %s", it->second->getName().c_str() );
      delete it->second;
      _programs.erase(it++);
    } else{
      ++it;
    }
  }
#endif
#ifdef JAVA_CODE
  java.util.Iterator it = _programs.entrySet().iterator();
  while (it.hasNext()) {
    java.util.Map.Entry pairs = (java.util.Map.Entry)it.next();
    GPUProgram program = (GPUProgram) pairs.getValue();
    if (program.getNReferences() == 0) {
      ILogger.instance().logInfo("Deleting program %s", program.getName() );
      it.remove();
    }
  }
#endif
}
예제 #2
0
//-----------------------------------------------------------------------------------------------------------------------------------------------------
Ptr<GPUProgram> Context::CreateGPUProgram( Ptr<VertexShader> pVertexShader, Ptr<FragmentShader> pFragmentShader )
{
  GPUProgram* pProgram = new GPUProgram(this);
  if (pVertexShader)
    pProgram->Attach(pVertexShader);
  if (pFragmentShader)
    pProgram->Attach(pFragmentShader);
  return pProgram;
}
예제 #3
0
void GCL::RenderComponent::Render(const Matrix44 &proj)
{
    const RenderObject *tempRenderObject = mObj;
    if (tempRenderObject->IsVisible())
    {
        const Material &tempMaterial = tempRenderObject->GetMaterial();
        tempMaterial.Bind();
        const Matrix44 &transform = mParentActor->GetTransform();
        GPUProgram *tempProgram = tempMaterial.GetShader();
        tempProgram->SetProjectionMatrix(proj);
        tempProgram->SetModelViewMatrix(transform);
        tempRenderObject->GetVBO().Render();
    }
}
bool GPUProgramManager::loadGPUProgram(const char* name, const char* vertexProgram, const char* fragmentProgram, const char* geometryProgram, int GS_inputPrimitiveType, int GS_outputPrimitiveType, int GS_maxVerticesOut)
{
	bool ret = false;
	//load the gpu program using vertex and fragment shader source
	GPUProgram* gpup = new GPUProgram();
	if(gpup->load(vertexProgram,fragmentProgram,geometryProgram,GS_inputPrimitiveType,GS_outputPrimitiveType,GS_maxVerticesOut))
	{
		this->gpuPrograms[name] = gpup;
		ret = true;
	}
	else
		delete gpup;
	return ret;
}
예제 #5
0
void FramebufferObject::bindRenderablesToOutput (GraphicAPI * api) {
    GPUProgram* program = api->getCurrentProgram();
    // TODO: remove the hard coded 16
    std::vector<Texture2D*> textures(16);
    if(program == NULL) return;
    int boundNames = 0;
    std::map<std::string,Texture2D*>::iterator it;
    for(it = renderables.begin(); it != renderables.end(); it++) {
        int location = program->getOutputLocation(it->first);
        if(location != -1) {
            textures[location] = it->second;
            boundNames++;
        }
    }
    textures.resize(boundNames);
    useRenderables(textures);
}
예제 #6
0
void VPLShaderManager::drawBackground(const Sensor *sensor,
		const Transform &projectionTransform, Float scaleFactor) {
	if (m_backgroundProgram == NULL)
		return;

	const Transform &trafo = sensor->getWorldTransform()->eval(0);

	Transform clipToWorld = trafo
		* Transform::scale(Vector(-1, 1, -1)) * projectionTransform.inverse();

	GPUProgram *prog = m_backgroundProgram;
	int tuOffset = 0;
	prog->bind();
	m_backgroundDependencies.bind(prog, m_backgroundDependencies, tuOffset);

	if (sensor->getType() & Sensor::EOrthographicCamera) {
		Vector d = trafo(Vector(0.0f, 0.0f, 1.0f));
		prog->setParameter(m_backgroundParam_camDirection, d);
	} else {
		Point p = trafo(Point(0.0f));
		prog->setParameter(m_backgroundParam_camPosition, p);
	}

	prog->setParameter(m_backgroundParam_emitterScale, scaleFactor);
	prog->setParameter(m_backgroundParam_clipToWorld, clipToWorld);
	m_renderer->blitQuad(false);
	prog->unbind();
	m_backgroundDependencies.unbind();
}
예제 #7
0
GPUProgram* GPUProgramManager::getCompiledProgram(int uniformsCode, int attributesCode) {
#ifdef C_CODE
  for (std::map<std::string, GPUProgram*>::iterator it = _programs.begin(); it != _programs.end(); ++it) {
    //#warning GPUProgram getUniformsCode avoid call
    GPUProgram* p = it->second;
    if (p->getUniformsCode() == uniformsCode && p->getAttributesCode() == attributesCode) {
      return p;
    }
  }
#endif
#ifdef JAVA_CODE
  for (final GPUProgram p : _programs.values()) {
    if ((p.getUniformsCode() == uniformsCode) && (p.getAttributesCode() == attributesCode)) {
      return p;
    }
  }
#endif
  return NULL;
}
예제 #8
0
GPUProgram* GPUProgramManager::getProgram(GL* gl, int uniformsCode, int attributesCode) {
  GPUProgram* p = getCompiledProgram(uniformsCode, attributesCode);
  if (p == NULL) {
    p = getNewProgram(gl, uniformsCode, attributesCode);
    if (p == NULL) {
      ILogger::instance()->logError("Problem at compiling program.");
      return NULL;
    }

    //#warning AVOID getAttributesCode and getUniformsCode calls
    if (p->getAttributesCode() != attributesCode ||
        p->getUniformsCode() != uniformsCode) {
      //#warning GIVE MORE DETAIL
      ILogger::instance()->logError("New compiled program does not match GL state.");
    }
  }

  p->addReference();

  return p;
}
예제 #9
0
void Sprite::Render(const Matrix44 &proj)
{
	if (!IsVisible())
		return;
	//RenderPipe::BufferCommands();
	const RenderObject *tempRenderObject = mObj;
	const Material &tempMaterial = tempRenderObject->GetMaterial();
	tempMaterial.Bind();
	const Texture &currentTexture = *(mTextureList[0]);
	currentTexture.Bind();
	const Matrix44 &transform = mTransform;
	GPUProgram *tempProgram = tempMaterial.GetShader();
	tempProgram->SetProjectionMatrix(proj);
	tempProgram->SetModelViewMatrix(transform);
	tempProgram->SetUniform("CurrentFrame", (long)mCurrentFrame);
	tempProgram->SetUniform("Dimension", Point2<long>(long(mHeader.width), long(mHeader.height)));
	tempProgram->SetUniform("FrameCount", (long)mHeader.frameCount);
	tempProgram->SetUniform("TextureSize", Point2<long>((long)currentTexture.GetResourceWidth(), (long)currentTexture.GetResourceHeight()));
	tempProgram->SetTextureSampler(currentTexture);

	tempRenderObject->GetVBO().Render();
	//RenderPipe::FlushCommands();
}
예제 #10
0
void VPLShaderManager::setScene(const Scene *scene) {
	if (scene == m_scene || (scene && m_scene && scene->getShapes() == m_scene->getShapes())) {
		m_scene = scene;
		return; /* This is still the same scene! Do nothing.. */
	}

	if (m_scene) {
		/* Unregister any content from the previous scene (which was uploaded to the GPU) */
		const ref_vector<Shape> &oldShapes = m_scene->getShapes();
		for (size_t i=0; i<oldShapes.size(); ++i) {
			const Shape *shape = oldShapes[i].get();

			if (shape->getClass()->getName() == "Instance") {
				const Instance *instance = static_cast<const Instance *>(shape);
				const std::vector<const Shape *> &instantiatedShapes =
						instance->getShapeGroup()->getKDTree()->getShapes();

				for (size_t j=0; j<instantiatedShapes.size(); ++j) {
					shape = instantiatedShapes[j];
					if (!m_renderer->unregisterGeometry(shape))
						continue;
					const BSDF *bsdf = shape->getBSDF();
					if (!bsdf)
						bsdf = const_cast<Shape *>(shape)->createTriMesh()->getBSDF();
					m_renderer->unregisterShaderForResource(bsdf);
				}
			} else {
				const BSDF *bsdf = shape->getBSDF();
				if (!bsdf)
					bsdf = const_cast<Shape *>(shape)->createTriMesh()->getBSDF();

				if (!m_renderer->unregisterGeometry(shape))
					continue;
				m_renderer->unregisterShaderForResource(bsdf);
			}
		}

		const ref_vector<Emitter> &emitters = m_scene->getEmitters();
		for (size_t i=0; i<emitters.size(); ++i)
			m_renderer->unregisterShaderForResource(emitters[i].get());

		/* Release all active GPU programs */
		std::map<std::string, VPLConfiguration>::iterator it = m_configurations.begin();
		for (; it != m_configurations.end(); ++it) {
			GPUProgram *program = (*it).second.program;
			program->cleanup();
			program->decRef();
		}
		m_configurations.clear();

		if (m_backgroundProgram) {
			m_backgroundProgram->cleanup();
			m_backgroundProgram = NULL;
		}
	}

	m_scene = scene;
	m_vplIndex = 0;

	if (!scene)
		return;

	const ref_vector<Shape> &shapes = scene->getShapes();
	m_geometry.clear();
	m_geometry.reserve(shapes.size());
	m_opaqueGeometry.clear();
	m_opaqueGeometry.reserve(shapes.size());
	m_animatedGeometry.clear();

	Matrix4x4 identityTrafo;
	identityTrafo.setIdentity();

	/* Upload all geometry to the GPU, create shaders for scattering models */
	for (size_t i=0; i<shapes.size(); ++i) {
		const Shape *shape = shapes[i].get();

		if (shape->getClass()->getName() == "Instance") {
			const Instance *instance = static_cast<const Instance *>(shape);
			const std::vector<const Shape *> &instantiatedShapes =
					instance->getShapeGroup()->getKDTree()->getShapes();
			const AnimatedTransform *atrafo = instance->getWorldTransform();
			const Matrix4x4 &trafo = atrafo->eval(0).getMatrix();

			for (size_t j=0; j<instantiatedShapes.size(); ++j) {
				shape = instantiatedShapes[j];
				GPUGeometry *gpuGeo = m_renderer->registerGeometry(shape);
				if (!gpuGeo)
					continue;

				const BSDF *bsdf = shape->getBSDF();
				if (!bsdf)
					bsdf = gpuGeo->getTriMesh()->getBSDF();

				Shader *shader = m_renderer->registerShaderForResource(bsdf);
				if (shader && !shader->isComplete()) {
					m_renderer->unregisterShaderForResource(bsdf);
					shader = NULL;
				}

				gpuGeo->setShader(shader);
				ssize_t geometryIndex = (ssize_t) m_geometry.size(), opaqueGeometryIndex = -1;
				m_geometry.push_back(std::make_pair(gpuGeo, trafo));

				if (shader && !(shader->getFlags() & Shader::ETransparent)) {
					opaqueGeometryIndex = (ssize_t) m_opaqueGeometry.size();
					m_opaqueGeometry.push_back(std::make_pair(gpuGeo, trafo));
				}

				if (!atrafo->isStatic()) {
					m_animatedGeometry.push_back(AnimatedGeometryRecord(atrafo,
						geometryIndex, opaqueGeometryIndex));
				}
			}
		} else {
			GPUGeometry *gpuGeo = m_renderer->registerGeometry(shape);
			if (!gpuGeo)
				continue;
			const BSDF *bsdf = shape->getBSDF();
			if (!bsdf)
				bsdf = gpuGeo->getTriMesh()->getBSDF();
			Shader *shader = m_renderer->registerShaderForResource(bsdf);
			if (shader && !shader->isComplete()) {
				m_renderer->unregisterShaderForResource(bsdf);
				shader = NULL;
			}
			gpuGeo->setShader(shader);
			m_geometry.push_back(std::make_pair(gpuGeo, identityTrafo));

			if (shader && !(shader->getFlags() & Shader::ETransparent))
				m_opaqueGeometry.push_back(std::make_pair(gpuGeo, identityTrafo));
		}
	}

	const ref_vector<Emitter> &emitters = scene->getEmitters();
	for (size_t i=0; i<emitters.size(); ++i)
		m_renderer->registerShaderForResource(emitters[i].get());

	if (scene->hasEnvironmentEmitter()) {
		Shader *shader = m_renderer->getShaderForResource(m_scene->getEnvironmentEmitter());
		m_backgroundDependencies = DependencyNode(shader);

		int id = 0;
		std::ostringstream oss;
		std::string evalName = m_backgroundDependencies.generateCode(oss, id);
		std::string marker = SUPPLEMENTAL_CODE_MARKER;
		std::string code = sh_background_frag;
		size_t insertionPos = code.find(marker);
		Assert(insertionPos != std::string::npos);
		code.replace(insertionPos, marker.length(), oss.str());

		ref<GPUProgram> prog = m_renderer->createGPUProgram("Background program");
		prog->setSource(GPUProgram::EVertexProgram, sh_background_vert);
		prog->setSource(GPUProgram::EFragmentProgram, code.c_str());
		prog->define("BACKGROUND_EVAL_NAME", evalName + "_background");

		if (scene->getSensor()->getType() & Sensor::EOrthographicCamera)
			prog->define("DIRECTIONAL_CAMERA");

		prog->init();

		id = 0;
		m_backgroundDependencies.resolve(prog, id);
		m_backgroundProgram = prog;
		m_backgroundParam_camPosition = prog->getParameterID("camPosition", false);
		m_backgroundParam_camDirection = prog->getParameterID("camDirection", false);
		m_backgroundParam_clipToWorld = prog->getParameterID("clipToWorld", false);
		m_backgroundParam_emitterScale = prog->getParameterID("emitterScale", false);
	}

	std::vector<size_t> geometryPermutation(m_geometry.size()),
	                    opaqueGeometryPermutation(m_opaqueGeometry.size());

	for (size_t i=0; i<m_geometry.size(); ++i)
		geometryPermutation[i] = i;
	for (size_t i=0; i<m_opaqueGeometry.size(); ++i)
		opaqueGeometryPermutation[i] = i;

	/// Sort using the MaterialOrder to reduce material changes/pipeline flushes
	std::sort(geometryPermutation.begin(),
	          geometryPermutation.end(), MaterialOrder(m_geometry));
	std::sort(opaqueGeometryPermutation.begin(),
	          opaqueGeometryPermutation.end(), MaterialOrder(m_opaqueGeometry));

	if (!m_animatedGeometry.empty()) {
		std::vector<size_t> geometryPermutationInv(m_geometry.size()),
		                    opaqueGeometryPermutationInv(m_opaqueGeometry.size());

		for (size_t i=0; i<m_geometry.size(); ++i)
			geometryPermutationInv[geometryPermutation[i]] = i;
		for (size_t i=0; i<m_opaqueGeometry.size(); ++i)
			opaqueGeometryPermutationInv[opaqueGeometryPermutation[i]] = i;

		for (size_t i=0; i<m_animatedGeometry.size(); ++i) {
			AnimatedGeometryRecord &agRec = m_animatedGeometry[i];
			if (agRec.geometryIndex >= 0)
				agRec.geometryIndex = geometryPermutationInv[agRec.geometryIndex];
			if (agRec.opaqueGeometryIndex >= 0)
				agRec.opaqueGeometryIndex = opaqueGeometryPermutationInv[agRec.opaqueGeometryIndex];
		}
	}

	permute_inplace(&m_geometry[0], geometryPermutation);
	permute_inplace(&m_opaqueGeometry[0], opaqueGeometryPermutation);
}
예제 #11
0
void VPLShaderManager::bind(const VPL &vpl, const BSDF *bsdf, const Sensor *sensor,
		const Emitter *emitter, const Matrix4x4 &instanceTransform, bool faceNormals) {
	Shader *bsdfShader = m_renderer->getShaderForResource(bsdf);
	Shader *vplShader = (vpl.type == EPointEmitterVPL || vpl.type == EDirectionalEmitterVPL)
		? m_renderer->getShaderForResource(vpl.emitter)
		: m_renderer->getShaderForResource(vpl.its.getBSDF());
	Shader *emitterShader = (emitter == NULL) ? NULL
		: m_renderer->getShaderForResource(emitter);

	/* Find situations in which we won't be able to render the
	   object properly ...  Case 1: one of the shaders is missing */
	bool unsupported = bsdfShader == NULL || vplShader == NULL ||
		(emitter != NULL && emitterShader == NULL);

	/* The material uses face normals (which have to be generated on the fly), and:
	     case 2: anisotropy is active as well
	     case 3: the graphics card does not support geometry shaders
	*/
	if (faceNormals)
		unsupported |= (bsdf->getType() & BSDF::EAnisotropic)
			|| !m_renderer->getCapabilities()->isSupported(
				RendererCapabilities::EGeometryShaders);

	if (unsupported) {
		std::map<std::string, VPLConfiguration>::iterator it
			= m_configurations.find("unsupported");
		m_targetConfiguration = VPLConfiguration();
		if (it != m_configurations.end()) {
			/* A program for this configuration has been created previously */
			m_currentProgram = (*it).second;
		} else {
			m_currentProgram = VPLConfiguration();
			ref<GPUProgram> prog = m_renderer->createGPUProgram("Unsupported material program");
			prog->setSource(GPUProgram::EVertexProgram, sh_unsupported_vert);
			prog->setSource(GPUProgram::EFragmentProgram, sh_unsupported_frag);
			prog->init();
			prog->incRef();
			m_currentProgram.program = prog;

			m_currentProgram.param_instanceTransform = prog->getParameterID("instanceTransform", false);
			m_configurations["unsupported"] = m_currentProgram;
		}
		GPUProgram *prog = m_currentProgram.program;
		prog->bind();
		prog->setParameter(m_currentProgram.param_instanceTransform, instanceTransform);
		return;
	}

	m_targetConfiguration = VPLConfiguration(vplShader,
		bsdfShader, emitterShader, faceNormals);

	m_alpha = bsdfShader->getAlpha();

	/* Generate a fingerprint of this shader chain, and check if it is known */
	std::string fingerprint = m_targetConfiguration.toString();

	if (m_diffuseSources)
		fingerprint += ", ds";
	if (m_diffuseReceivers)
		fingerprint += ", dr";

	std::map<std::string, VPLConfiguration>::iterator it
		= m_configurations.find(fingerprint);

	bool directionalCamera = false;
	if (sensor->getType() & Sensor::EOrthographicCamera) {
		directionalCamera = true;
	} else if (!(sensor->getType() & Sensor::EPerspectiveCamera)) {
		/* Sensor is neither a perspective nor orthographic camera */
		Log(EError, "Unsupported sensor type!");
	}

	if (it != m_configurations.end()) {
		/* A program for this configuration has been created previously */
		m_currentProgram = (*it).second;
	} else {
		std::ostringstream oss;
		std::string vplEvalName, bsdfEvalName, emitterEvalName;
		m_targetConfiguration.generateCode(oss, vplEvalName, bsdfEvalName, emitterEvalName);
		m_currentProgram = m_targetConfiguration;

		ref<GPUProgram> prog = m_renderer->createGPUProgram(fingerprint);
		prog->setSource(GPUProgram::EVertexProgram, sh_render_vert);

		if (faceNormals) {
			prog->setSource(GPUProgram::EGeometryProgram, sh_render_geom);
			prog->setInputGeometryType(GPUProgram::ETriangles);
			prog->setOutputGeometryType(GPUProgram::ETriangleStrips);
			prog->setMaxVertices(3);
		}

		std::string code(sh_render_frag);
		std::string marker(SUPPLEMENTAL_CODE_MARKER);
		size_t insertionPos = code.find(marker);
		Assert(insertionPos != std::string::npos);
		code.replace(insertionPos, marker.length(), oss.str());

		prog->setSource(GPUProgram::EFragmentProgram, code);

		if (bsdf->getType() & BSDF::EAnisotropic)
			prog->define("ANISOTROPIC");

		if (fingerprint.find("VertexColor") != std::string::npos)
			prog->define("VERTEX_COLORS");

		if (m_shadowMapType == ShadowMapGenerator::EDirectional)
			prog->define("DIRECTIONAL_VPL");
		else if (m_shadowMapType == ShadowMapGenerator::EParaboloid)
			prog->define("PARABOLOIDAL_VPL");
		else
			prog->define("CUBEMAP_VPL");

		if (directionalCamera)
			prog->define("DIRECTIONAL_CAMERA");

		if (faceNormals)
			prog->define("FACE_NORMALS");

		if (vpl.type == EDirectionalEmitterVPL || vpl.type == EPointEmitterVPL) {
			prog->define("EMITTER_VPL");
			prog->define("VPL_EVAL_NAME", vplEvalName + "_dir");
		} else {
			if (m_diffuseSources)
				prog->define("VPL_EVAL_NAME", vplEvalName + "_diffuse");
			else
				prog->define("VPL_EVAL_NAME", vplEvalName);
		}

		if (vpl.type == ESurfaceVPL || (vpl.type == EPointEmitterVPL &&
				vpl.emitter->getType() & Emitter::EOnSurface))
			prog->define("VPL_ON_SURFACE");

		if (emitterShader) {
			prog->define("EMITTER_AREA_EVAL_NAME", emitterEvalName + "_area");
			prog->define("EMITTER_DIR_EVAL_NAME", emitterEvalName + "_dir");
		}

		if (m_diffuseReceivers)
			prog->define("BSDF_EVAL_NAME", bsdfEvalName + "_diffuse");
		else
			prog->define("BSDF_EVAL_NAME", bsdfEvalName);

		prog->init();
		prog->incRef();
		m_currentProgram.program = prog;

		m_currentProgram.param_camPosition       = prog->getParameterID("camPosition", false);
		m_currentProgram.param_camDirection      = prog->getParameterID("camDirection", false);
		m_currentProgram.param_vplPosition       = prog->getParameterID("vplPosition", false);
		m_currentProgram.param_vplDirection      = prog->getParameterID("vplDirection", false);
		m_currentProgram.param_vplPower          = prog->getParameterID("vplPower", false);
		m_currentProgram.param_vplTransform      = prog->getParameterID("vplTransform", false);
		m_currentProgram.param_vplFrame          = prog->getParameterID("vplFrame", false);
		m_currentProgram.param_vplUV             = prog->getParameterID("vplUV", false);
		m_currentProgram.param_vplWi             = prog->getParameterID("vplWi", false);
		m_currentProgram.param_minDistSqr        = prog->getParameterID("minDistSqr", false);
		m_currentProgram.param_emitterScale      = prog->getParameterID("emitterScale", false);
		m_currentProgram.param_depthRange        = prog->getParameterID("depthRange", false);
		m_currentProgram.param_instanceTransform = prog->getParameterID("instanceTransform", false);
		m_currentProgram.param_shadowMap         = prog->getParameterID("shadowMap", false);
		m_currentProgram.resolve(prog);
		m_configurations[fingerprint] = m_currentProgram;

		statsMaxResidentShaders.recordMaximum(m_configurations.size() + m_shadowGen->getShaderCount());
	}

	GPUProgram *prog = m_currentProgram.program;
	prog->bind();

	Float minDist = m_nearClip + (m_farClip - m_nearClip) * m_clamping;
	prog->setParameter(m_currentProgram.param_instanceTransform, instanceTransform);
	prog->setParameter(m_currentProgram.param_vplTransform, m_shadowMapTransform);
	prog->setParameter(m_currentProgram.param_depthRange, Vector2(m_nearClip, m_farClip));
	prog->setParameter(m_currentProgram.param_vplPower, vpl.P);
	prog->setParameter(m_currentProgram.param_vplFrame,
		Matrix3x3(vpl.its.shFrame.s, vpl.its.shFrame.t, vpl.its.shFrame.n));
	prog->setParameter(m_currentProgram.param_vplUV, vpl.its.uv);
	prog->setParameter(m_currentProgram.param_vplWi, vpl.its.wi);
	prog->setParameter(m_currentProgram.param_shadowMap, m_shadowMap);
	prog->setParameter(m_currentProgram.param_minDistSqr, minDist*minDist);
	prog->setParameter(m_currentProgram.param_emitterScale, vpl.emitterScale);

	if (directionalCamera) {
		Vector d = sensor->getWorldTransform()->eval(0)(Vector(0.0f, 0.0f, 1.0f));
		prog->setParameter(m_currentProgram.param_camDirection, d);
	} else {
		Point p = sensor->getWorldTransform()->eval(0).transformAffine(Point(0.0f));
		prog->setParameter(m_currentProgram.param_camPosition, p);
	}

	if (m_shadowMapType == ShadowMapGenerator::EDirectional)
		prog->setParameter(m_currentProgram.param_vplDirection, vpl.its.shFrame.n);
	else
		prog->setParameter(m_currentProgram.param_vplPosition, vpl.its.p);

	m_targetConfiguration.bind(m_currentProgram, 1);
}
예제 #12
0
/*
 * FIXME: Stupid argument ordering
 */
void GenericRenderer::set_auto_uniforms_on_shader(GPUProgram& program,
    CameraID camera,
    Renderable &subactor) {

    //Calculate the modelview-projection matrix
    Mat4 modelview_projection;
    Mat4 modelview;

    const Mat4 model = subactor.final_transformation();
    const Mat4& view = window().camera(camera)->view_matrix();
    const Mat4& projection = window().camera(camera)->projection_matrix();

    kmMat4Multiply(&modelview, &view, &model);
    kmMat4Multiply(&modelview_projection, &projection, &modelview);

    if(program.uniforms().uses_auto(SP_AUTO_VIEW_MATRIX)) {
        program.uniforms().set_mat4x4(
            program.uniforms().auto_variable_name(SP_AUTO_VIEW_MATRIX),
            view
        );
    }

    if(program.uniforms().uses_auto(SP_AUTO_MODELVIEW_PROJECTION_MATRIX)) {
        program.uniforms().set_mat4x4(
            program.uniforms().auto_variable_name(SP_AUTO_MODELVIEW_PROJECTION_MATRIX),
            modelview_projection
        );
    }

    if(program.uniforms().uses_auto(SP_AUTO_MODELVIEW_MATRIX)) {
        program.uniforms().set_mat4x4(
            program.uniforms().auto_variable_name(SP_AUTO_MODELVIEW_MATRIX),
            modelview
        );
    }

    if(program.uniforms().uses_auto(SP_AUTO_PROJECTION_MATRIX)) {
        program.uniforms().set_mat4x4(
            program.uniforms().auto_variable_name(SP_AUTO_PROJECTION_MATRIX),
            projection
        );
    }

    if(program.uniforms().uses_auto(SP_AUTO_INVERSE_TRANSPOSE_MODELVIEW_MATRIX)) {
        Mat3 inverse_transpose_modelview;

        kmMat4ExtractRotationMat3(&modelview, &inverse_transpose_modelview);
        kmMat3Inverse(&inverse_transpose_modelview, &inverse_transpose_modelview);
        kmMat3Transpose(&inverse_transpose_modelview, &inverse_transpose_modelview);

        program.uniforms().set_mat3x3(
            program.uniforms().auto_variable_name(SP_AUTO_INVERSE_TRANSPOSE_MODELVIEW_MATRIX),
            inverse_transpose_modelview
        );
    }
/*
    if(pass.uses_auto_uniform(SP_AUTO_MATERIAL_AMBIENT)) {
        pass.program()->uniforms().set_colour(
            pass.auto_uniform_variable_name(SP_AUTO_MATERIAL_AMBIENT),
            pass.ambient()
        );
    }

    if(pass.uses_auto_uniform(SP_AUTO_MATERIAL_DIFFUSE)) {
        pass.program()->uniforms().set_colour(
            pass.auto_uniform_variable_name(SP_AUTO_MATERIAL_DIFFUSE),
            pass.diffuse()
        );
    }

    if(pass.uses_auto_uniform(SP_AUTO_MATERIAL_SPECULAR)) {
        pass.program()->uniforms().set_colour(
            pass.auto_uniform_variable_name(SP_AUTO_MATERIAL_SPECULAR),
            pass.specular()
        );
    }

    if(pass.uses_auto_uniform(SP_AUTO_MATERIAL_SHININESS)) {
        pass.program()->uniforms().set_float(
            pass.auto_uniform_variable_name(SP_AUTO_MATERIAL_SHININESS),
            pass.shininess()
        );
    }

    if(pass.uses_auto_uniform(SP_AUTO_MATERIAL_ACTIVE_TEXTURE_UNITS)) {
        pass.program()->uniforms().set_int(
            pass.auto_uniform_variable_name(SP_AUTO_MATERIAL_ACTIVE_TEXTURE_UNITS),
            pass.texture_unit_count()
        );
    }*/
}
예제 #13
0
void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, 
			const Luminaire *luminaire, const Point &camPos, bool faceNormals) {
	Shader *bsdfShader = m_renderer->getShaderForResource(bsdf);
	Shader *vplShader = (vpl.type == ELuminaireVPL)
		? m_renderer->getShaderForResource(vpl.luminaire)
		: m_renderer->getShaderForResource(vpl.its.shape->getBSDF());
	Shader *lumShader = (luminaire == NULL) ? NULL 
		: m_renderer->getShaderForResource(luminaire);
	std::ostringstream oss;

	if (bsdfShader == NULL || vplShader == NULL ||
		(luminaire != NULL && lumShader == NULL)) {
		/* Unsupported! */
		m_renderer->setColor(Spectrum(0.0f));
		return;
	}

	bool anisotropic = bsdf->getType() & BSDF::EAnisotropic;

	m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader, 
			lumShader, faceNormals);
	m_targetConfig.toString(oss);
	std::string configName = oss.str();
	std::map<std::string, ProgramAndConfiguration>::iterator it =
		m_programs.find(configName);
	GPUProgram *program = NULL;

	if (it != m_programs.end()) {
		/* A program for this configuration has been created previously */
		m_current = (*it).second;
		program = m_current.program;
	} else {
		/* No program for this particular combination exists -- create one */
		program = m_renderer->createGPUProgram(configName);

		if (faceNormals) {
			/* Generate face normals in a geometry shader */
	
    		if (!m_renderer->getCapabilities()->isSupported(
					RendererCapabilities::EGeometryShaders))
				Log(EError, "Face normals require geometry shader support!");
			if (anisotropic)
				Log(EError, "Anisotropy and face normals can't be combined at the moment");
	
			oss.str("");
			oss << "#version 120" << endl
				<< "#extension GL_EXT_geometry_shader4 : enable" << endl
				<< "varying in vec3 lightVec_vertex[3], camVec_vertex[3];" << endl
				<< "varying in vec2 uv_vertex[3];" << endl
				<< "varying in vec3 vertexColor_vertex[3];" << endl
				<< "varying out vec3 normal;" << endl
				<< "varying out vec3 lightVec, camVec;" << endl
				<< "varying out vec2 uv;" << endl
				<< "varying out vec3 vertexColor;" << endl
				<< endl
				<< "void main() {" << endl
				<< "   vec3 edge1 = camVec_vertex[0]-camVec_vertex[1];" << endl
				<< "   vec3 edge2 = camVec_vertex[0]-camVec_vertex[2];" << endl
				<< "   normal = normalize(cross(edge1, edge2));" << endl
				<< "   gl_Position = vec4(0.0);" << endl
				<< "   lightVec = camVec = vec3(0.0);" << endl
				<< "   for (int i=0; i<gl_VerticesIn; ++i) {" << endl
				<< "      gl_Position = gl_PositionIn[i];" << endl
				<< "      uv = uv_vertex[i];" << endl
				<< "      vertexColor = vertexColor_vertex[i];" << endl
				<< "      lightVec = lightVec_vertex[i];" << endl
				<< "      camVec = camVec_vertex[i];" << endl
				<< "      EmitVertex();" << endl
				<< "   }" << endl
				<< "   EndPrimitive();" << endl
				<< "}" << endl;

			program->setMaxVertices(3); 
			program->setSource(GPUProgram::EGeometryProgram, oss.str());
		}

		/* Vertex program */
		oss.str("");
        oss << "#version 120" << endl;
		if (anisotropic)
			oss << "varying vec3 tangent;" << endl;
		oss << "uniform vec3 vplPos, camPos;" << endl;

		if (!faceNormals) {
			oss << "varying vec3 lightVec, camVec;" << endl
				<< "varying vec2 uv;" << endl
				<< "varying vec3 normal;" << endl
				<< "varying vec3 vertexColor;" << endl
				<< endl
				<< "void main() {" << endl
				<< "   uv = gl_MultiTexCoord0.xy;" << endl
				<< "   camVec = camPos - gl_Vertex.xyz;" << endl
				<< "   lightVec = vplPos - gl_Vertex.xyz;" << endl
				<< "   gl_Position = ftransform();" << endl
				<< "   vertexColor = gl_Color.rgb;" << endl
				<< "   normal = gl_Normal;" << endl;
		} else {
			oss << "varying vec3 lightVec_vertex, camVec_vertex;" << endl
				<< "varying vec2 uv_vertex;" << endl
				<< "varying vec3 vertexColor_vertex;" << endl
				<< endl
				<< "void main() {" << endl
				<< "   uv_vertex = gl_MultiTexCoord0.xy;" << endl
				<< "   camVec_vertex = camPos - gl_Vertex.xyz;" << endl
				<< "   lightVec_vertex = vplPos - gl_Vertex.xyz;" << endl
				<< "   gl_Position = ftransform();" << endl
				<< "   vertexColor_vertex = gl_Color.rgb;" << endl;
		}
		if (anisotropic)
			oss << "   tangent = gl_MultiTexCoord1.xyz;" << endl;
		oss << "}" << endl;

		program->setSource(GPUProgram::EVertexProgram, oss.str());
		oss.str("");

		oss << "#version 120" << endl
			<< endl
			<< "/* Uniform inputs */" << endl
			<< "uniform samplerCube shadowMap;" << endl
			<< "uniform vec3 vplPower, vplS, vplT, vplN, vplWi;" << endl
			<< "uniform float nearClip, invClipRange, minDist, alpha;" << endl
			<< "uniform vec2 vplUV;" << endl
			<< "uniform bool diffuseSources, diffuseReceivers;" << endl
			<< "varying vec3 vertexColor;" << endl
			<< endl
			<< "/* Inputs <- Vertex program */" << endl
			<< "varying vec3 normal, lightVec, camVec;" << endl
			<< "varying vec2 uv;" << endl;
		if (anisotropic)
			oss << "varying vec3 tangent;" << endl;

		oss << endl
			<< "/* Some helper functions for BSDF implementations */" << endl
			<< "float cosTheta(vec3 v) { return v.z; }" << endl
			<< "float sinTheta2(vec3 v) { return 1.0-v.z*v.z; }" << endl
			<< "float sinTheta(vec3 v) { float st2 = sinTheta2(v); if (st2 <= 0) return 0.0; else return sqrt(sinTheta2(v)); }" << endl
			<< "float tanTheta(vec3 v) { return sinTheta(v)/cosTheta(v); }" << endl
			<< "float sinPhi(vec3 v) { return v.y/sinTheta(v); }" << endl
			<< "float cosPhi(vec3 v) { return v.x/sinTheta(v); }" << endl
			<< "const float pi = 3.141592653589;" << endl
			<< "const float inv_pi = 0.318309886183791;" << endl
			<< endl;

		std::string vplEvalName, bsdfEvalName, lumEvalName;
		m_targetConfig.generateCode(oss, vplEvalName, bsdfEvalName, lumEvalName);

		oss << "void main() {" << endl
			<< "   /* Set up an ONB */" << endl
			<< "   vec3 N = normalize(normal);" << endl;
		if (anisotropic) {
			oss << "   vec3 S = normalize(tangent - dot(tangent, N)*N);" << endl;
		} else {
			oss << "   vec3 S;" << endl
				<< "   if (abs(N.x) > abs(N.y)) {" << endl
				<< "        float invLen = 1.0 / sqrt(N.x*N.x + N.z*N.z);" << endl
				<< "        S = vec3(-N.z * invLen, 0.0, N.x * invLen);" << endl
				<< "   } else {" << endl
				<< "        float invLen = 1.0 / sqrt(N.y*N.y + N.z*N.z);" << endl
				<< "        S = vec3(0.0, -N.z * invLen, N.y * invLen);" << endl
				<< "   }" << endl;
		}
		oss << "   vec3 T = cross(N, S);" << endl
			<< endl
			<< "   /* Compute shadows */" << endl
			<< "   float d = length(lightVec);" << endl
			<< "   vec3 nLightVec = lightVec/d, absLightVec = abs(lightVec);" << endl
			<< "   float depth = max(max(absLightVec.x, absLightVec.y), absLightVec.z);" << endl
			<< "   depth = (depth-nearClip) * invClipRange - 0.005;" << endl
			<< "   float shadow = textureCube(shadowMap, nLightVec).r > depth ? 1.0 : 0.0;" << endl
			<< endl
			<< "   /* Shading */" << endl
			<< "   vec3 nCamVec = normalize(camVec);" << endl
			<< "   vec3 wo = vec3(dot(S, nLightVec)," << endl
			<< "                  dot(T, nLightVec)," << endl
			<< "                  dot(N, nLightVec));" << endl
			<< "   vec3 wi = vec3(dot(S, nCamVec)," << endl
			<< "                  dot(T, nCamVec)," << endl
			<< "                  dot(N, nCamVec));" << endl
			<< "   vec3 vplWo = -vec3(dot(vplS, nLightVec)," << endl
			<< "                      dot(vplT, nLightVec)," << endl
			<< "                      dot(vplN, nLightVec));" << endl
			<< "   vec3 contrib = vplPower;" << endl
			<< "   if (!diffuseSources)" << endl 
			<< "      contrib *= " << vplEvalName;
			if (vpl.type == ESurfaceVPL)
				oss << "(vplUV, vplWi, vplWo);" << endl;
			else
				oss << "_dir(vplWo);" << endl;
			if (vpl.type == ESurfaceVPL)
				oss << "   else contrib *= max(0, cosTheta(vplWo));" << endl;
		oss << "   if (d < minDist) d = minDist;" << endl
			<< "   if (!diffuseReceivers)" << endl
			<< "      contrib *= "<< bsdfEvalName << "(uv, wi, wo);" << endl
			<< "   else" << endl
			<< "      contrib *= " << bsdfEvalName << "_diffuse(uv, wi, wo);" << endl
			<< "   gl_FragColor.rgb = contrib";
		if (vpl.type == ELuminaireVPL 
				&& (vpl.luminaire->getType() & Luminaire::EOnSurface))
			oss << " * (shadow * abs(cosTheta(vplWo)) / (d*d))";
		else 
			oss << " * (shadow / (d*d))";
		if (luminaire != NULL) {
			oss << endl;
			oss << "                      + " << lumEvalName << "_area(uv)"
				<< " * " << lumEvalName << "_dir(wi);" << endl;
		} else {
			oss << ";" << endl;
		}
		oss << "   gl_FragColor.a = alpha;" << endl
			<< "}" << endl;

		program->setSource(GPUProgram::EFragmentProgram, oss.str());
		try {
			program->init();
		} catch (const std::exception &) {
			Log(EWarn, "Unable to compile the following VPL program:\n%s", oss.str().c_str());
			throw;
		}

		m_targetConfig.resolve(program);
		m_targetConfig.param_shadowMap = program->getParameterID("shadowMap", false);
		m_targetConfig.param_vplPos = program->getParameterID("vplPos", false);
		m_targetConfig.param_camPos = program->getParameterID("camPos", false);
		m_targetConfig.param_vplPower = program->getParameterID("vplPower", false);
		m_targetConfig.param_vplN = program->getParameterID("vplN", false);
		m_targetConfig.param_vplS = program->getParameterID("vplS", false);
		m_targetConfig.param_vplT = program->getParameterID("vplT", false);
		m_targetConfig.param_vplWi = program->getParameterID("vplWi", false);
		m_targetConfig.param_vplUV = program->getParameterID("vplUV", false);
		m_targetConfig.param_nearClip = program->getParameterID("nearClip", false);
		m_targetConfig.param_invClipRange = program->getParameterID("invClipRange", false);
		m_targetConfig.param_minDist = program->getParameterID("minDist", false);
		m_targetConfig.param_diffuseSources = program->getParameterID("diffuseSources", false);
		m_targetConfig.param_diffuseReceivers = program->getParameterID("diffuseReceivers", false);
		m_targetConfig.param_alpha = program->getParameterID("alpha", false);
		m_current.program = program;
		m_current.config = m_targetConfig;
		m_programs[configName] = m_current;
		program->incRef();
	}

	program->bind();
	m_shadowMap->bind(0);

	const VPLProgramConfiguration &config = m_current.config;

	program->setParameter(config.param_shadowMap, m_shadowMap);
	program->setParameter(config.param_vplPos, vpl.its.p);
	program->setParameter(config.param_camPos, camPos);
	program->setParameter(config.param_vplN, vpl.its.shFrame.n);
	program->setParameter(config.param_vplS, vpl.its.shFrame.s);
	program->setParameter(config.param_vplT, vpl.its.shFrame.t);
	
	program->setParameter(config.param_alpha, 
		bsdfShader->getFlags() & Shader::ETransparent ? 0.5f : 1.0f);

	if (vpl.type == ESurfaceVPL) {
		program->setParameter(config.param_vplWi, vpl.its.wi);
		program->setParameter(config.param_vplUV, vpl.its.uv);
		program->setParameter(config.param_diffuseSources, m_diffuseSources);
	}

	Spectrum power = vpl.P;
	if (m_diffuseSources && vpl.type == ESurfaceVPL)
		power *= vpl.its.shape->getBSDF()->getDiffuseReflectance(vpl.its) * INV_PI;
	program->setParameter(config.param_vplPower, power);
	program->setParameter(config.param_diffuseReceivers, m_diffuseReceivers);
	program->setParameter(config.param_nearClip, m_nearClip);
	program->setParameter(config.param_invClipRange, m_invClipRange);
	program->setParameter(config.param_minDist, m_minDist);

	int textureUnitOffset = 1;
	m_targetConfig.bind(program, config, textureUnitOffset);
}