void findDecals(Storm3D_Scene &scene)
	{
		decals.clear();

		// Find decals
		{
			IStorm3D_Camera *camera = scene.GetCamera();
			Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera);

			Frustum frustum = stormCamera->getFrustum();
			Tree::FrustumIterator itf(*tree, frustum);
			for(; !itf.end(); itf.next())
				decals.push_back(*itf);

			std::sort(decals.begin(), decals.end(), DecalSorter());
		}
	}
	void renderShadows(Storm3D_Scene &scene)
	{
		// this is BROKEN
		// FIXME
		// just clear the list
		shadowDecals.clear();
		return;

		createIndexBuffers();

		int renderAmount = 0;
		if(!shadowDecals.empty())
		{
			IStorm3D_Camera *camera = scene.GetCamera();
			Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera);
			Frustum frustum = stormCamera->getFrustum();

			shadowVertices.create(shadowDecals.size() * 4, VERTEX_SIZE, true);

			int rawSize = shadowDecals.size() * 4 * VERTEX_SIZE;
			void *ramBuffer = malloc(rawSize);
			void *lockPointer = shadowVertices.lock();
			VXFORMAT_DECAL *buffer = reinterpret_cast<VXFORMAT_DECAL *> (ramBuffer);

			float inverseRange =1.f / fogRange;
			for(unsigned int i = 0; i < shadowDecals.size(); ++i)
			{
				const StormDecal &decal = shadowDecals[i];
				Sphere sphere(decal.position, decal.getRadius());
				if(frustum.visibility(sphere))
				{
					float factor = decal.position.y - fogEnd;
					factor *= inverseRange;
					if(factor < 0.f)
						factor = 0.f;
					if(factor > 1.f)
						factor = 1.f;
					factor = 1.f - factor;

					COL color = decal.light;
					color.r += factor * (1.f - color.r);
					color.g += factor * (1.f - color.g);
					color.b += factor * (1.f - color.b);

					DWORD vertexColor = color.GetAsD3DCompatibleARGB() & 0x00FFFFFF;

					DWORD oldColor = decal.vertexColor;
					decal.vertexColor = vertexColor;
					decal.insert(buffer);
					decal.vertexColor = oldColor;

					buffer += 4;
					++renderAmount;
				}
			}

			if(renderAmount)
			{
				if(renderAmount > STORM_MAX_DECAL_AMOUNT)
					renderAmount = STORM_MAX_DECAL_AMOUNT;
				memcpy(lockPointer, ramBuffer, renderAmount * 4 * VERTEX_SIZE);
			}

			free(ramBuffer);
			shadowVertices.unlock();
		}

		D3DXMATRIX tm;

		frozenbyte::storm::VertexShader::disable();
		frozenbyte::storm::PixelShader::disable();
		Storm3D_ShaderManager::GetSingleton()->SetWorldTransform(tm);

		applyFVF(DECAL_FVF, VERTEX_SIZE);
		glActiveTexture(GL_TEXTURE0);
		glClientActiveTexture(GL_TEXTURE0);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
		glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
		glActiveTexture(GL_TEXTURE1);
		glClientActiveTexture(GL_TEXTURE1);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_3D);
		glDisable(GL_TEXTURE_CUBE_MAP);

		glDepthMask(GL_FALSE);
		glEnable(GL_BLEND);
		glDisable(GL_ALPHA_TEST);
		glBlendFunc(GL_ZERO, GL_SRC_COLOR);

		if(renderAmount && shadowMaterial)
		{
			shadowVertices.apply(0);
			shadowMaterial->applyShadow();

			indices.render(renderAmount * 2, renderAmount * 4);
			scene.AddPolyCounter(renderAmount * 2);
		}

		glDepthMask(GL_TRUE);
		glDisable(GL_BLEND);
		shadowDecals.clear();
	}
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize)
{
	D3DXMATRIX light;
	D3DXVECTOR3 lightPosition(position.x, position.y, position.z);
	D3DXVECTOR3 up(0, 1.f, 0);
	D3DXVECTOR3 lookAt = lightPosition;
	lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z);
	D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up);

	D3DXVECTOR3 v[5];
	v[0] = D3DXVECTOR3(0, 0, 0);
	v[1] = D3DXVECTOR3(0, 0, 1.f);
	v[2] = D3DXVECTOR3(0, 0, 1.f);
	v[3] = D3DXVECTOR3(0, 0, 1.f);
	v[4] = D3DXVECTOR3(0, 0, 1.f);

	int minX = screenSize.x;
	int minY = screenSize.y;
	int maxX = 0;
	int maxY = 0;

	float det = D3DXMatrixDeterminant(&light);
	D3DXMatrixInverse(&light, &det, &light);

	float angle = D3DXToRadian(fov) * .5f;
	for(int i = 0; i <= 4; ++i)
	{
		if(i > 0)
		{
			float z = v[i].z;
			if(i == 1 || i == 2)
			{
				v[i].x = z * sinf(angle);
				v[i].z = z * cosf(angle);
			}
			else
			{
				v[i].x = z * sinf(-angle);
				v[i].z = z * cosf(-angle);
			}

			if(i == 1 || i == 3)
				v[i].y = z * sinf(angle);
			else
				v[i].y = z * sinf(-angle);

			float scale = range / cosf(angle);
			v[i] *= scale;
		}

		D3DXVec3TransformCoord(&v[i], &v[i], &light);
	}

	const Frustum &frustum = camera.getFrustum();
	calculateLineToScissor(toVC3(v[0]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[0]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[0]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[0]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[1]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[2]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[3]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY);
	calculateLineToScissor(toVC3(v[4]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY);

	/*
	VC3 cameraPos = camera.GetPosition();
	VC3 cameraPosResult;
	float cameraRhw = 0, cameraRealZ = 0;
	bool cameraVisible = camera.GetTransformedToScreen(cameraPos, cameraPosResult, cameraRhw, cameraRealZ);

	for(i = 0; i <= 4; ++i)
	{
		VC3 source(v[i].x, v[i].y, v[i].z);
		VC3 result;
		float rhw = 0, realZ = 0;
		bool inFront = camera.GetTransformedToScreen(source, result, rhw, realZ);

		// HAX HAX!

		result.x = std::max(0.f, result.x);
		result.y = std::max(0.f, result.y);
		result.x = std::min(1.f, result.x);
		result.y = std::min(1.f, result.y);

		//if(fabsf(rhw) < 0.0001f)
		//	continue;

		bool flip = false;
		if(realZ < cameraRealZ)
			flip = true;

		if(flip)
		{
			result.x = 1.f - result.x;
			result.y = 1.f - result.y;

			//minX = 0;
			//minY = 0;
			//maxX = screenSize.x;
			//maxY = screenSize.y;
		}

		int x = int(result.x * screenSize.x);
		int y = int(result.y * screenSize.y);

		maxX = std::max(x, maxX);
		maxY = std::max(y, maxY);
		minX = std::min(x, minX);
		minY = std::min(y, minY);
	}
	*/

	if(maxX > screenSize.x)
		maxX = screenSize.x;
	if(maxY > screenSize.y)
		maxY = screenSize.y;
	if(minX < 0)
		minX = 0;
	if(minY < 0)
		minY = 0;

	RECT rc;
	rc.left = minX;
	rc.top = minY;
	rc.right = maxX;
	rc.bottom = maxY;

	if(rc.left < rc.right && rc.top < rc.bottom)
	{
		device.SetScissorRect(&rc);
		device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
	}
	else
	{
		RECT rc;
		rc.left = 0;
		rc.top = 0;
		rc.right = 1;
		rc.bottom = 1;

		device.SetScissorRect(&rc);
		device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);

		return false;
	}

	return true;
}
Exemplo n.º 4
0
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize, Storm3D_Scene *scene)
{
	D3DXMATRIX light;
	D3DXVECTOR3 lightPosition(position.x, position.y, position.z);
	D3DXVECTOR3 up(0, 1.f, 0);
	D3DXVECTOR3 lookAt = lightPosition;
	lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z);
	D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up);

	// Create frustum vertices

	D3DXVECTOR3 v[5];
	v[0] = D3DXVECTOR3(0, 0, 0);
	v[1] = D3DXVECTOR3(0, 0, 1.f);
	v[2] = D3DXVECTOR3(0, 0, 1.f);
	v[3] = D3DXVECTOR3(0, 0, 1.f);
	v[4] = D3DXVECTOR3(0, 0, 1.f);

	float det = D3DXMatrixDeterminant(&light);
	D3DXMatrixInverse(&light, &det, &light);
	float angle = D3DXToRadian(fov) * .5f;
	for(int i = 0; i <= 4; ++i)
	{
		if(i > 0)
		{
			float z = v[i].z;
			if(i == 1 || i == 2)
			{
				v[i].x = z * sinf(angle);
				v[i].z = z * cosf(angle);
			}
			else
			{
				v[i].x = z * sinf(-angle);
				v[i].z = z * cosf(-angle);
			}

			if(i == 1 || i == 3)
				v[i].y = z * sinf(angle);
			else
				v[i].y = z * sinf(-angle);

			float scale = range / cosf(angle);
			v[i] *= scale;
		}

		D3DXVec3TransformCoord(&v[i], &v[i], &light);
	}

	// Create area

	const Frustum &frustum = camera.getFrustum();
	int minX = screenSize.x;
	int minY = screenSize.y;
	int maxX = 0;
	int maxY = 0;

	for(int i = 0; i < 6; ++i)
	{
		VC3 v1;
		VC3 v2;
		VC3 v3;

		if(i == 0)
		{
			v1 = toVC3(v[0]);
			v2 = toVC3(v[1]);
			v3 = toVC3(v[2]);
		}
		else if(i == 1)
		{
			v1 = toVC3(v[0]);
			v2 = toVC3(v[2]);
			v3 = toVC3(v[4]);
		}
		else if(i == 2)
		{
			v1 = toVC3(v[0]);
			v2 = toVC3(v[3]);
			v3 = toVC3(v[4]);
		}
		else if(i == 3)
		{
			v1 = toVC3(v[0]);
			v2 = toVC3(v[1]);
			v3 = toVC3(v[3]);
		}
		else if(i == 4)
		{
			v1 = toVC3(v[1]);
			v2 = toVC3(v[2]);
			v3 = toVC3(v[3]);
		}
		else if(i == 5)
		{
			v1 = toVC3(v[4]);
			v2 = toVC3(v[2]);
			v3 = toVC3(v[3]);
		}

		const ClipPolygon &clipPolygon = clipTriangleToFrustum(v1, v2, v3, frustum);
		for(int j = 0; j < clipPolygon.vertexAmount; ++j)
		{
			VC3 result;
			float rhw = 0.f;
			float real_z = 0.f;
			camera.GetTransformedToScreen(clipPolygon.vertices[j], result, rhw, real_z);

			int x = int(result.x * screenSize.x);
			int y = int(result.y * screenSize.y);
			//if(x < -1 || x > screenSize.x)
			//	continue;
			//if(y < -1 || x > screenSize.y)
			//	continue;

			x = max(x, 0);
			y = max(y, 0);
			x = min(x, screenSize.x - 1);
			y = min(y, screenSize.y - 1);

			maxX = max(x, maxX);
			maxY = max(y, maxY);
			minX = min(x, minX);
			minY = min(y, minY);

			/*
			// Visualize clipped polygons
			if(scene)
			{
				VC3 p1 = clipPolygon.vertices[j];
				VC3 p2 = clipPolygon.vertices[(j + 1) % clipPolygon.vertexAmount];


				for(int k = 0; k < 5; ++k)
				{
					const VC3 &planeNormal = frustum.planeNormals[k];
					PLANE plane;

					if(k == 0)
						plane.MakeFromNormalAndPosition(planeNormal, frustum.position + planeNormal);
					else
						plane.MakeFromNormalAndPosition(planeNormal, frustum.position);
	
					float d1 = plane.GetPointRange(p1);
					float d2 = plane.GetPointRange(p2);

					if(d1 < .25f)
						p1 += planeNormal * (.25f - d1);
					if(d2 < .25f)
						p2 += planeNormal * (.25f - d2);
				}

				scene->AddLine(p1, p2, COL(1.f, 1.f, 1.f));
			}
			*/
		}
	}

	RECT rc;
	bool visible = false;

	if(maxX > minX && maxY > minY)
	{
		visible = true;
		rc.left = minX;
		rc.top = minY;
		rc.right = maxX;
		rc.bottom = maxY;
	}
	else
	{
		visible = false;
		rc.left = 0;
		rc.top = 0;
		rc.right = 1;
		rc.bottom = 1;
	}
/*
	// Visualize scissor area
	if(scene && visible)
	{
		static DWORD foo = GetTickCount();
		int dif = (GetTickCount() - foo) % 2000;
		if(dif < 1000)
			scene->Render2D_Picture(0, VC2(float(minX), float(minY)), VC2(float(maxX - minX), float(maxY - minY)), 0.5f, 0.f, 0, 0, 0, 0, false);
	}
*/
	device.SetScissorRect(&rc);
	device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);

	return visible;
}
    void renderShadows(Storm3D_Scene &scene)
    {
        gfx::Renderer& renderer = storm.renderer;
        gfx::Device& device = renderer.device;
        gfx::ProgramManager& programManager = renderer.programManager;

        if (shadowDecals.empty() || !shadowMaterial)
            return;

        int renderAmount = 0;

        IStorm3D_Camera *camera = scene.GetCamera();
        Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera);
        Frustum frustum = stormCamera->getFrustum();

        uint32_t baseVertex = 0;
        Vertex_P3DUV *buffer = 0;;
        renderer.lockDynVtx<Vertex_P3DUV>(shadowDecals.size() * 4, &buffer, &baseVertex);

        float inverseRange = 1.f / fogRange;
        for (unsigned int i = 0; i < shadowDecals.size() && renderAmount < MAX_DECAL_AMOUNT; ++i)
        {
            const Decal &decal = shadowDecals[i];
            Sphere sphere(decal.position, decal.getRadius());
            if (frustum.visibility(sphere))
            {
                float factor = decal.position.y - fogEnd;
                factor *= inverseRange;
                factor = std::max(0.0f, factor);
                factor = std::min(1.0f, factor);
                factor = 1.f - factor;

                COL color = decal.light;
                color.r += factor * (1.f - color.r);
                color.g += factor * (1.f - color.g);
                color.b += factor * (1.f - color.b);

                uint32_t vertexColor = color.as_u32_D3D_ARGB(decal.alpha);
                decal.insert(buffer, vertexColor);

                buffer += 4;
                ++renderAmount;
            }
        }

        renderer.unlockDynVtx();

        if (renderAmount == 0)
            return;

        D3DXMATRIX tm;
        D3DXMatrixIdentity(&tm);

        programManager.setProgram( gfx::ProgramManager::DECAL_SHADOW);
        programManager.setWorldMatrix(tm);
        programManager.applyState(device);

        device.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
        device.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        device.SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
        device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
        device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);

        if (shadowMaterial->baseTexture)
            shadowMaterial->baseTexture->Apply(0);

        renderer.setFVF(FVF_P3DUV);
        renderer.setDynVtxBuffer<Vertex_P3DUV>();
        renderer.drawQuads(baseVertex, renderAmount);

        device.SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
        device.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

        shadowDecals.clear();
    }