예제 #1
0
void CSM3GroundDrawer::DrawShadowPass()
{
	if (!shadowrc)
		return;

	shadowCam.fov = camera->GetHalfFov()*2.0f; // Why *2?
	shadowCam.front = camera->forward;
	shadowCam.right = camera->right;
	shadowCam.up = camera->up;
	shadowCam.pos = camera->GetPos();
	shadowCam.aspect = 1.0f;

	Shader::IProgramObject* po =
		shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MAP);

	glPolygonOffset(1, 1);
	glEnable(GL_POLYGON_OFFSET_FILL);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);

	po->Enable();
	tr->SetActiveContext(shadowrc);
	tr->DrawSimple();
	tr->SetActiveContext(rc);
	po->Disable();

	glCullFace(GL_BACK);
	glDisable(GL_CULL_FACE);

	glDisable(GL_POLYGON_OFFSET_FILL);
}
예제 #2
0
Shader::IProgramObject* CShaderHandler::CreateProgramObject(
    const std::string& poClass,
    const std::string& poName,
    const std::string& vsStr,
    const std::string& vsDefs,
    const std::string& fsStr,
    const std::string& fsDefs,
    bool arbProgram
) {
    Shader::IProgramObject* po = CreateProgramObject(poClass, poName, arbProgram);

    if (po->IsValid()) {
        return po;
    }

    Shader::IShaderObject* vso = CreateShaderObject(vsStr, vsDefs, (arbProgram? GL_VERTEX_PROGRAM_ARB: GL_VERTEX_SHADER));
    Shader::IShaderObject* fso = CreateShaderObject(fsStr, fsDefs, (arbProgram? GL_FRAGMENT_PROGRAM_ARB: GL_FRAGMENT_SHADER));

    po->AttachShaderObject(vso);
    po->AttachShaderObject(fso);
    po->Link();

    if (!po->IsValid()) {
        logOutput.Print("[CShaderHandler::CreateProgramObject]\n");
        logOutput.Print("\tprogram-object name: %s, link-log:\n%s\n", poName.c_str(), po->GetLog().c_str());
    }
    return po;
}
예제 #3
0
bool SMFRenderStateGLSL::HasValidShader(const DrawPass::e& drawPass) const {
	Shader::IProgramObject* shader = nullptr;

	switch (drawPass) {
		case DrawPass::TerrainDeferred: { shader = glslShaders[GLSL_SHADER_DEFERRED]; } break;
		default:                        { shader = glslShaders[GLSL_SHADER_CURRENT ]; } break;
	}

	return (shader != nullptr && shader->IsValid());
}
예제 #4
0
// shadow-pass state management funcs
// FIXME: setup face culling for S3O?
static void SetupDefShadowUnitDrawState(unsigned int modelType, bool deferredPass) {
	glDisable(GL_TEXTURE_2D);

	glPolygonOffset(1.0f, 1.0f);
	glEnable(GL_POLYGON_OFFSET_FILL);

	Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MODEL);
	po->Enable();
	po->SetUniformMatrix4fv(1, false, shadowHandler->GetShadowViewMatrix());
	po->SetUniformMatrix4fv(2, false, shadowHandler->GetShadowProjMatrix());
}
예제 #5
0
void CSMFGroundDrawer::DrawBorder(const DrawPass::e drawPass)
{
	ISMFRenderState* prvState = smfRenderStates[RENDER_STATE_SEL];
	Shader::IProgramObject* shaderProg = &borderShader;

	// no need to enable, does nothing
	smfRenderStates[RENDER_STATE_SEL] = smfRenderStates[RENDER_STATE_NOP];


	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	glActiveTexture(GL_TEXTURE2);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, smfMap->GetDetailTexture());

	glActiveTexture(GL_TEXTURE0);
	glEnable(GL_TEXTURE_2D);

	glEnable(GL_BLEND);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE * wireframe + GL_FILL * (1 - wireframe));

	#if 0
	if (mapRendering->voidWater && (drawPass != DrawPass::WaterReflection)) {
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.9f);
	}
	#endif

	shaderProg->Enable();
	shaderProg->SetUniformMatrix4x4<const char*, float>("u_movi_mat", false, camera->GetViewMatrix());
	shaderProg->SetUniformMatrix4x4<const char*, float>("u_proj_mat", false, camera->GetProjectionMatrix());
	meshDrawer->DrawBorderMesh(drawPass); // calls back into ::SetupBigSquare
	shaderProg->Disable();

	#if 0
	if (mapRendering->voidWater && (drawPass != DrawPass::WaterReflection))
		glDisable(GL_ALPHA_TEST);
	#endif

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glDisable(GL_BLEND);

	glActiveTexture(GL_TEXTURE2);
	glDisable(GL_TEXTURE_2D);

	glActiveTexture(GL_TEXTURE0);
	glDisable(GL_TEXTURE_2D);

	glDisable(GL_CULL_FACE);


	smfRenderStates[RENDER_STATE_SEL] = prvState;
}
예제 #6
0
void CShaderHandler::ReleaseProgramObjectsMap(ProgramObjMap& poMap) {
	for (auto it = poMap.cbegin(); it != poMap.cend(); ++it) {
		Shader::IProgramObject* po = it->second;

		// free the program object and its attachments
		if (po != Shader::nullProgramObject) {
			po->Release(); delete po;
		}
	}

	poMap.clear();
}
예제 #7
0
bool SMFRenderStateARB::HasValidShader(const DrawPass::e& drawPass) const {
	Shader::IProgramObject* shader = nullptr;

	switch (drawPass) {
		case DrawPass::Normal:          { shader = arbShaders[ARB_SHADER_CURRENT]; } break;
		case DrawPass::WaterReflection: { shader = arbShaders[ARB_SHADER_REFLECT]; } break;
		case DrawPass::WaterRefraction: { shader = arbShaders[ARB_SHADER_REFRACT]; } break;
		default: {} break;
	}

	return (shader != nullptr && shader->IsValid());
}
예제 #8
0
void CShadowHandler::LoadShadowGenShaderProgs()
{
	shadowGenProgs.resize(SHADOWGEN_PROGRAM_LAST);

	static const std::string shadowGenProgNames[SHADOWGEN_PROGRAM_LAST] = {
		"ARB/unit_genshadow.vp",
		"ARB/groundshadow.vp",
		"ARB/treeShadow.vp",
		"ARB/treeFarShadow.vp",
		"ARB/projectileshadow.vp",
	};
	static const std::string shadowGenProgHandles[SHADOWGEN_PROGRAM_LAST] = {
		"ShadowGenShaderProgModel",
		"ShadowGenshaderProgMap",
		"ShadowGenshaderProgTreeNear",
		"ShadowGenshaderProgTreeDist",
		"ShadowGenshaderProgProjectile",
	};
	static const std::string shadowGenProgDefines[SHADOWGEN_PROGRAM_LAST] = {
		"#define SHADOWGEN_PROGRAM_MODEL\n",
		"#define SHADOWGEN_PROGRAM_MAP\n",
		"#define SHADOWGEN_PROGRAM_TREE_NEAR\n",
		"#define SHADOWGEN_PROGRAM_TREE_DIST\n",
		"#define SHADOWGEN_PROGRAM_PROJECTILE\n",
	};

	CShaderHandler* sh = shaderHandler;

	if (globalRendering->haveGLSL) {
		for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) {
			Shader::IProgramObject* po = sh->CreateProgramObject("[ShadowHandler]", shadowGenProgHandles[i] + "GLSL", false);
			Shader::IShaderObject* so = sh->CreateShaderObject("GLSL/ShadowGenVertProg.glsl", shadowGenProgDefines[i], GL_VERTEX_SHADER);

			po->AttachShaderObject(so);
			po->Link();
			po->SetUniformLocation("shadowParams");
			po->SetUniformLocation("cameraDirX");    // used by SHADOWGEN_PROGRAM_TREE_NEAR
			po->SetUniformLocation("cameraDirY");    // used by SHADOWGEN_PROGRAM_TREE_NEAR
			po->SetUniformLocation("treeOffset");    // used by SHADOWGEN_PROGRAM_TREE_NEAR

			shadowGenProgs[i] = po;

		}
	} else {
		for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) {
			Shader::IProgramObject* po = sh->CreateProgramObject("[ShadowHandler]", shadowGenProgHandles[i] + "ARB", true);
			Shader::IShaderObject* so = sh->CreateShaderObject(shadowGenProgNames[i], "", GL_VERTEX_PROGRAM_ARB);

			po->AttachShaderObject(so);
			po->Link();

			shadowGenProgs[i] = po;
		}
	}

	drawShadows = true;
}
예제 #9
0
void CFeatureDrawer::DrawShadowPass()
{
	glPolygonOffset(1.0f, 1.0f);
	glEnable(GL_POLYGON_OFFSET_FILL);

	Shader::IProgramObject* po =
		shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MODEL);

	po->Enable();

	{
		GML_RECMUTEX_LOCK(feat); // DrawShadowPass

		// note: for the shadow-pass, we want to make sure
		// out-of-view features casting frustum-intersecting
		// shadows are still rendered, but this is expensive
		// and does not make much difference
		//
		// GetVisibleFeatures(1, false);

		// need the alpha-mask for transparent features
		glEnable(GL_TEXTURE_2D);
		glPushAttrib(GL_COLOR_BUFFER_BIT);
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.5f);

		// needed for 3do models (else they will use any currently bound texture)
		// note: texture0 is by default a 1x1 texture with rgba(0,0,0,255)
		// (we are just interested in the 255 alpha here)
		glBindTexture(GL_TEXTURE_2D, 0);

		// 3DO's have clockwise-wound faces and
		// (usually) holes, so disable backface
		// culling for them
		glDisable(GL_CULL_FACE);
		DrawOpaqueFeatures(MODELTYPE_3DO);
		glEnable(GL_CULL_FACE);

		for (int modelType = MODELTYPE_S3O; modelType < MODELTYPE_OTHER; modelType++) {
			DrawOpaqueFeatures(modelType);
		}

		glPopAttrib();
		glDisable(GL_TEXTURE_2D);
	}

	po->Disable();

	glDisable(GL_POLYGON_OFFSET_FILL);
}
예제 #10
0
void CSMFGroundDrawer::DrawWaterPlane(bool drawWaterReflection) {
	if (drawWaterReflection)
		return;

	GL::RenderDataBuffer& buffer = waterPlaneBuffers[1 - (camera->GetPos().IsInBounds() && !mapRendering->voidWater)];
	Shader::IProgramObject* shader = &buffer.GetShader();

	shader->Enable();
	shader->SetUniformMatrix4x4<const char*, float>("u_movi_mat", false, camera->GetViewMatrix());
	shader->SetUniformMatrix4x4<const char*, float>("u_proj_mat", false, camera->GetProjectionMatrix());
	shader->SetUniform("planeOffset", std::min(-200.0f, smfMap->GetCurrMinHeight() - 400.0f));
	buffer.Submit(GL_TRIANGLE_STRIP, 0, buffer.GetNumElems<VA_TYPE_C>());
	shader->Disable();
}
예제 #11
0
void CSMFGroundDrawer::DrawShadowPass(void)
{
	if (mapInfo->map.voidWater && readmap->currMaxHeight < 0.0f) {
		return;
	}

	Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MAP);

	glEnable(GL_POLYGON_OFFSET_FILL);

	glPolygonOffset(-1.f, -1.f);
		po->Enable();
			meshDrawer->DrawMesh(DrawPass::Shadow);
		po->Disable();

	glDisable(GL_POLYGON_OFFSET_FILL);
}
예제 #12
0
Shader::IProgramObject* CShaderHandler::CreateProgramObject(
	const std::string& poClass,
	const std::string& poName,
	const std::string& vsStr,
	const std::string& vsDefs,
	const std::string& fsStr,
	const std::string& fsDefs,
	bool arbProgram
) {
	Shader::IProgramObject* po = CreateProgramObject(poClass, poName, arbProgram);

	if (po->IsValid()) {
		return po;
	}

	Shader::IShaderObject* vso = CreateShaderObject(vsStr, vsDefs, (arbProgram? GL_VERTEX_PROGRAM_ARB: GL_VERTEX_SHADER));
	Shader::IShaderObject* fso = CreateShaderObject(fsStr, fsDefs, (arbProgram? GL_FRAGMENT_PROGRAM_ARB: GL_FRAGMENT_SHADER));

	po->AttachShaderObject(vso);
	po->AttachShaderObject(fso);
	po->Link();
	po->Validate();

	if (!po->IsValid()) {
		const char* fmt = "[%s]\n\tprogram-object name: %s, link-log:\n%s";
		const char* log = po->GetLog().c_str();
		LOG_L(L_WARNING, fmt, __FUNCTION__, poName.c_str(), log);
	}
	return po;
}
예제 #13
0
void CSMFGroundDrawer::DrawShadowPass()
{
	if (!globalRendering->drawGround)
		return;
	if (readMap->HasOnlyVoidWater())
		return;

	Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MAP);

	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(spPolygonOffsetScale, spPolygonOffsetUnits); // dz*s + r*u

		// also render the border geometry to prevent light-visible backfaces
		po->Enable();
		po->SetUniformMatrix4fv(1, false, shadowHandler->GetShadowViewMatrix());
		po->SetUniformMatrix4fv(2, false, shadowHandler->GetShadowProjMatrix());
			meshDrawer->DrawMesh(DrawPass::Shadow);
			meshDrawer->DrawBorderMesh(DrawPass::Shadow);
		po->Disable();

	glDisable(GL_POLYGON_OFFSET_FILL);
}
예제 #14
0
void CProjectileDrawer::DrawShadowPass()
{
	Shader::IProgramObject* po =
		shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_PROJECTILE);

	glDisable(GL_TEXTURE_2D);
	po->Enable();

	CProjectile::inArray = false;
	CProjectile::va = GetVertexArray();
	CProjectile::va->Initialize();

	{
		GML_RECMUTEX_LOCK(proj); // DrawShadowPass

		for (int modelType = MODELTYPE_3DO; modelType < MODELTYPE_OTHER; modelType++) {
			DrawProjectilesShadow(modelType);
		}

		// draw the model-less projectiles
		DrawProjectilesSetShadow(renderProjectiles);
	}

	if (CProjectile::inArray) {
		glEnable(GL_TEXTURE_2D);
		textureAtlas->BindTexture();
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		glAlphaFunc(GL_GREATER,0.3f);
		glEnable(GL_ALPHA_TEST);
		glShadeModel(GL_SMOOTH);

		ph->currentParticles += CProjectile::DrawArray();
	}

	po->Disable();
	glShadeModel(GL_FLAT);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_TEXTURE_2D);
}
예제 #15
0
void CSMFGroundDrawer::CreateBorderShader() {
	std::string vsCode = std::move(Shader::GetShaderSource("GLSL/SMFBorderVertProg4.glsl"));
	std::string fsCode = std::move(Shader::GetShaderSource("GLSL/SMFBorderFragProg4.glsl"));

	Shader::GLSLShaderObject shaderObjs[2] = {{GL_VERTEX_SHADER, vsCode.c_str(), ""}, {GL_FRAGMENT_SHADER, fsCode.c_str(), ""}};
	Shader::IProgramObject* shaderProg = &borderShader;

	borderShader.AttachShaderObject(&shaderObjs[0]);
	borderShader.AttachShaderObject(&shaderObjs[1]);
	borderShader.ReloadShaderObjects();
	borderShader.CreateAndLink();
	borderShader.RecalculateShaderHash();
	borderShader.ClearAttachedShaderObjects();
	borderShader.Validate();

	shaderProg->Enable();
	shaderProg->SetUniformMatrix4x4<const char*, float>("u_movi_mat", false, CMatrix44f::Identity());
	shaderProg->SetUniformMatrix4x4<const char*, float>("u_proj_mat", false, CMatrix44f::Identity());
	shaderProg->SetUniform("u_diffuse_tex_sqr", -1, -1);
	shaderProg->SetUniform("u_diffuse_tex", 0);
	shaderProg->SetUniform("u_detail_tex", 2);
	shaderProg->Disable();
}
예제 #16
0
void CSMFGroundDrawer::CreateWaterPlanes(bool camOutsideMap) {
	{
		const float xsize = (smfMap->mapSizeX) >> 2;
		const float ysize = (smfMap->mapSizeZ) >> 2;
		const float size = std::min(xsize, ysize);
		const float alphainc = math::TWOPI / 32.0f;

		static std::vector<VA_TYPE_C> verts;

		verts.clear();
		verts.reserve(4 * (32 + 1) * 2);

		const unsigned char fogColor[4] = {
			(unsigned char)(255 * sky->fogColor[0]),
			(unsigned char)(255 * sky->fogColor[1]),
			(unsigned char)(255 * sky->fogColor[2]),
			 255
		};

		const unsigned char planeColor[4] = {
			(unsigned char)(255 * waterRendering->planeColor[0]),
			(unsigned char)(255 * waterRendering->planeColor[1]),
			(unsigned char)(255 * waterRendering->planeColor[2]),
			 255
		};

		float alpha;
		float r1;
		float r2;

		float3 p;

		for (int n = (camOutsideMap) ? 0 : 1; n < 4; ++n) {
			if ((n == 1) && !camOutsideMap) {
				// don't render vertices under the map
				r1 = 2.0f * size;
			} else {
				r1 = n * n * size;
			}

			if (n == 3) {
				// last stripe: make it thinner (looks better with fog)
				r2 = (n + 0.5) * (n + 0.5) * size;
			} else {
				r2 = (n + 1) * (n + 1) * size;
			}

			for (alpha = 0.0f; (alpha - math::TWOPI) < alphainc; alpha += alphainc) {
				p.x = r1 * fastmath::sin(alpha) + 2.0f * xsize;
				p.z = r1 * fastmath::cos(alpha) + 2.0f * ysize;

				verts.push_back(VA_TYPE_C{p, {planeColor}});

				p.x = r2 * fastmath::sin(alpha) + 2.0f * xsize;
				p.z = r2 * fastmath::cos(alpha) + 2.0f * ysize;

				verts.push_back(VA_TYPE_C{p, {(n == 3)? fogColor : planeColor}});
			}
		}

		waterPlaneBuffers[camOutsideMap].Init();
		waterPlaneBuffers[camOutsideMap].UploadC(verts.size(), 0, verts.data(), nullptr);
	}
	{
		char vsBuf[65536];
		char fsBuf[65536];

		const char* vsVars = "uniform float planeOffset;\n";
		const char* vsCode =
			"\tgl_Position = u_proj_mat * u_movi_mat * vec4(a_vertex_xyz + vec3(0.0, planeOffset, 0.0), 1.0);\n"
			"\tv_color_rgba = a_color_rgba;\n";
		const char* fsVars = "const float v_color_mult = 1.0 / 255.0;\n";
		const char* fsCode = "\tf_color_rgba = v_color_rgba * v_color_mult;\n";

		GL::RenderDataBuffer::FormatShaderC(vsBuf, vsBuf + sizeof(vsBuf), "", vsVars, vsCode, "VS");
		GL::RenderDataBuffer::FormatShaderC(fsBuf, fsBuf + sizeof(fsBuf), "", fsVars, fsCode, "FS");
		GL::RenderDataBuffer& renderDataBuffer = waterPlaneBuffers[camOutsideMap];

		Shader::GLSLShaderObject shaderObjs[2] = {{GL_VERTEX_SHADER, &vsBuf[0], ""}, {GL_FRAGMENT_SHADER, &fsBuf[0], ""}};
		Shader::IProgramObject* shaderProg = renderDataBuffer.CreateShader((sizeof(shaderObjs) / sizeof(shaderObjs[0])), 0, &shaderObjs[0], nullptr);

		shaderProg->Enable();
		shaderProg->SetUniformMatrix4x4<const char*, float>("u_movi_mat", false, CMatrix44f::Identity());
		shaderProg->SetUniformMatrix4x4<const char*, float>("u_proj_mat", false, CMatrix44f::Identity());
		shaderProg->SetUniform("planeOffset", 0.0f);
		shaderProg->Disable();
	}
}
예제 #17
0
static void ResetDefShadowUnitDrawState(unsigned int modelType, bool deferredPass) {
	Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MODEL);

	po->Disable();
	glDisable(GL_POLYGON_OFFSET_FILL);
}
예제 #18
0
void SMFRenderStateGLSL::Enable(const CSMFGroundDrawer* smfGroundDrawer, const DrawPass::e& drawPass) {
	if (useLuaShaders) {
		// use raw, GLSLProgramObject::Enable also calls RecompileIfNeeded
		glUseProgram(glslShaders[GLSL_SHADER_CURRENT]->GetObjID());
		// diffuse textures are always bound (SMFGroundDrawer::SetupBigSquare)
		glActiveTexture(GL_TEXTURE0);
		return;
	}

	Shader::IProgramObject* shader = glslShaders[GLSL_SHADER_CURRENT];

	const CSMFReadMap* smfMap = smfGroundDrawer->GetReadMap();

	const GL::LightHandler* cLightHandler = smfGroundDrawer->GetLightHandler();
	      GL::LightHandler* mLightHandler = const_cast<GL::LightHandler*>(cLightHandler); // XXX

	const float3 cameraPos = camera->GetPos();
	const float3 fogParams = {sky->fogStart, sky->fogEnd, globalRendering->viewRange};
	const float2 mapParams = {readMap->GetCurrMinHeight(), readMap->GetCurrMaxHeight()};

	shader->SetFlag("HAVE_SHADOWS", shadowHandler->ShadowsLoaded());
	shader->SetFlag("HAVE_INFOTEX", infoTextureHandler->IsEnabled());

	shader->Enable();
	shader->SetUniform2v<const char*, float>("mapHeights", &mapParams.x);
	shader->SetUniform3v<const char*, float>("cameraPos", &cameraPos.x);
	shader->SetUniformMatrix4x4<const char*, float>("viewMat", false, camera->GetViewMatrix());
	shader->SetUniformMatrix4x4<const char*, float>("viewMatInv", false, camera->GetViewMatrixInverse());
	shader->SetUniformMatrix4x4<const char*, float>("viewProjMat", false, camera->GetViewProjectionMatrix());
	shader->SetUniformMatrix4x4<const char*, float>("shadowMat", false, shadowHandler->GetShadowViewMatrix());
	shader->SetUniform4v<const char*, float>("shadowParams", shadowHandler->GetShadowParams());
	shader->SetUniform3v<const char*, float>("fogParams", &fogParams.x);
	shader->SetUniform<const char*, float>("infoTexIntensityMul", float(infoTextureHandler->InMetalMode()) + 1.0f);

	if (cLightHandler->NumConfigLights() > 0) {
		mLightHandler->Update();
		shader->SetUniform4v<const char*, float>("fwdDynLights", cLightHandler->NumUniformVecs(), cLightHandler->GetRawLightDataPtr());
	}

	switch (drawPass) {
		case DrawPass::WaterReflection: { shader->SetUniform4v<const char*, float>("clipPlane", IWater::MapReflClipPlane()); } break;
		case DrawPass::WaterRefraction: { shader->SetUniform4v<const char*, float>("clipPlane", IWater::MapRefrClipPlane()); } break;
		default: {} break;
	}

	if (shadowHandler->ShadowsLoaded())
		shadowHandler->SetupShadowTexSampler(GL_TEXTURE4);

	glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, smfMap->GetDetailTexture());
	glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D, smfMap->GetNormalsTexture());
	glActiveTexture(GL_TEXTURE6); glBindTexture(GL_TEXTURE_2D, smfMap->GetSpecularTexture());
	glActiveTexture(GL_TEXTURE7); glBindTexture(GL_TEXTURE_2D, smfMap->GetSplatDetailTexture());
	glActiveTexture(GL_TEXTURE8); glBindTexture(GL_TEXTURE_2D, smfMap->GetSplatDistrTexture());
	glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapHandler->GetSkyReflectionTextureID());
	glActiveTexture(GL_TEXTURE10); glBindTexture(GL_TEXTURE_2D, smfMap->GetSkyReflectModTexture());
	glActiveTexture(GL_TEXTURE11); glBindTexture(GL_TEXTURE_2D, smfMap->GetBlendNormalsTexture());
	glActiveTexture(GL_TEXTURE12); glBindTexture(GL_TEXTURE_2D, smfMap->GetLightEmissionTexture());
	glActiveTexture(GL_TEXTURE13); glBindTexture(GL_TEXTURE_2D, smfMap->GetParallaxHeightTexture());
	glActiveTexture(GL_TEXTURE14); glBindTexture(GL_TEXTURE_2D, infoTextureHandler->GetCurrentInfoTexture());

	for (int i = 0; i < CSMFReadMap::NUM_SPLAT_DETAIL_NORMALS; i++) {
		if (smfMap->GetSplatNormalTexture(i) != 0) {
			glActiveTexture(GL_TEXTURE15 + i); glBindTexture(GL_TEXTURE_2D, smfMap->GetSplatNormalTexture(i));
		}
	}

	glActiveTexture(GL_TEXTURE0);
}
예제 #19
0
void CAdvTreeDrawer::Draw(float treeDistance, bool drawReflection)
{
	const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0]: treeGen->farTex[1];
	const bool drawDetailed = ((treeDistance >= 4.0f) || drawReflection);

	CBaseGroundDrawer* gd = readmap->GetGroundDrawer();
	Shader::IProgramObject* treeShader = NULL;

	#define L mapInfo->light

	glEnable(GL_ALPHA_TEST);
	glEnable(GL_TEXTURE_2D);

	if (globalRendering->drawFog) {
		glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor);
		glEnable(GL_FOG);
	}


	if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, activeFarTex);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, shadowHandler->shadowTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);

		treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW];
		treeShader->Enable();

		if (globalRendering->haveGLSL) {
			treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]);
			treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x));
		} else {
			treeShader->SetUniformTarget(GL_FRAGMENT_PROGRAM_ARB);
			treeShader->SetUniform4f(10, L.groundAmbientColor.x, L.groundAmbientColor.y, L.groundAmbientColor.z, 1.0f);
			treeShader->SetUniform4f(11, 0.0f, 0.0f, 0.0f, 1.0f - (sky->GetLight()->GetGroundShadowDensity() * 0.5f));
			treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);

			glMatrixMode(GL_MATRIX0_ARB);
			glLoadMatrixf(shadowHandler->shadowMatrix.m);
			glMatrixMode(GL_MODELVIEW);
		}
	} else {
		glBindTexture(GL_TEXTURE_2D, activeFarTex);
	}


	const int cx = int(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE));
	const int cy = int(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE));

	CAdvTreeSquareDrawer drawer(this, cx, cy, treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE, drawDetailed);

	GML_STDMUTEX_LOCK(tree); // Draw

	oldTreeDistance = treeDistance;

	// draw far-trees using map-dependent grid-visibility
	readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer);


	if (drawDetailed) {
		// draw near-trees
		const int xstart = std::max(                              0, cx - 2);
		const int xend   = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2);
		const int ystart = std::max(                              0, cy - 2);
		const int yend   = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2);

		if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
			treeShader->Disable();
			treeShader = treeShaders[TREE_PROGRAM_NEAR_SHADOW];
			treeShader->Enable();

			if (globalRendering->haveGLSL) {
				treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]);
				treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x));
			}

			glActiveTexture(GL_TEXTURE1);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
			glActiveTexture(GL_TEXTURE0);
		} else {
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);

			treeShader = treeShaders[TREE_PROGRAM_NEAR_BASIC];
			treeShader->Enable();

			if (!globalRendering->haveGLSL) {
				#define MX (gs->pwr2mapx * SQUARE_SIZE)
				#define MY (gs->pwr2mapy * SQUARE_SIZE)
				treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
				treeShader->SetUniform4f(15, 1.0f / MX, 1.0f / MY, 1.0f / MX, 1.0f);
				#undef MX
				#undef MY
			}
		}


		if (globalRendering->haveGLSL) {
			treeShader->SetUniform3fv(0, &camera->right[0]);
			treeShader->SetUniform3fv(1, &camera->up[0]);
			treeShader->SetUniform2f(5, 0.20f * (1.0f / MAX_TREE_HEIGHT), 0.85f);
		} else {
			treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
			treeShader->SetUniform3f(13, camera->right.x, camera->right.y, camera->right.z);
			treeShader->SetUniform3f( 9, camera->up.x,    camera->up.y,    camera->up.z   );
			treeShader->SetUniform4f(11, L.groundSunColor.x,     L.groundSunColor.y,     L.groundSunColor.z,     0.85f);
			treeShader->SetUniform4f(14, L.groundAmbientColor.x, L.groundAmbientColor.y, L.groundAmbientColor.z, 0.85f);
			treeShader->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier
		}


		glAlphaFunc(GL_GREATER, 0.5f);
		glDisable(GL_BLEND);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		varr = GetVertexArray();
		varr->Initialize();

		static FadeTree fadeTrees[3000];
		FadeTree* pFT = fadeTrees;


		for (TreeSquareStruct* pTSS = trees + ystart * treesX; pTSS <= trees + yend * treesX; pTSS += treesX) {
			for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) {
				tss->lastSeen = gs->frameNum;
				varr->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes

				for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) {
					const TreeStruct* ts = &ti->second;
					const float3 pos(ts->pos);

					if (!camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2.0f, 0.0f), MAX_TREE_HEIGHT / 2.0f)) {
						continue;
					}

					const float camDist = (pos - camera->pos).SqLength();
					int type = ts->type;
					float dy = 0.0f;
					unsigned int displist;

					if (type < 8) {
						dy = 0.5f;
						displist = treeGen->pineDL + type;
					} else {
						type -= 8;
						dy = 0.0f;
						displist = treeGen->leafDL + type;
					}

					if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 110 * 110)) {
						// draw detailed near-distance tree (same as mid-distance trees without alpha)
						treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
					} else if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 125 * 125)) {
						// draw mid-distance tree
						const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15);

						treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z);

						glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f);
						glCallList(displist);
						glAlphaFunc(GL_GREATER, 0.5f);

						// save for second pass
						pFT->pos = pos;
						pFT->deltaY = dy;
						pFT->type = type;
						pFT->relDist = relDist;
						++pFT;
					} else {
						// draw far-distance tree
						DrawTreeVertex(varr, pos, type * 0.125f, dy, false);
					}
				}
			}
		}


		// reset the world-offset
		treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), 0.0f, 0.0f, 0.0f);

		// draw trees that have been marked as falling
		for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) {
			const float3 pos = fti->pos - UpVector * (fti->fallPos * 20);

			if (camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2, 0.0f), MAX_TREE_HEIGHT / 2.0f)) {
				const float ang = fti->fallPos * PI;

				const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang));
				const float3 zvec((yvec.cross(float3(-1.0f, 0.0f, 0.0f))).ANormalize());
				const float3 xvec(yvec.cross(zvec));

				CMatrix44f transMatrix(pos, xvec, yvec, zvec);

				glPushMatrix();
				glMultMatrixf(&transMatrix[0]);

				int type = fti->type;
				int displist = 0;

				if (type < 8) {
					displist = treeGen->pineDL + type;
				} else {
					type -= 8;
					displist = treeGen->leafDL + type;
				}

				glCallList(displist);
				glPopMatrix();
			}
		}


		if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
			treeShader->Disable();
			treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW];
			treeShader->Enable();

			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
			glActiveTexture(GL_TEXTURE0);
		} else {
			treeShader->Disable();
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
		}


		// draw far-distance trees
		varr->DrawArrayT(GL_QUADS);

		// draw faded mid-distance trees
		for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) {
			varr = GetVertexArray();
			varr->Initialize();
			varr->CheckInitSize(12 * VA_SIZE_T);

			DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false);

			glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f));
			varr->DrawArrayT(GL_QUADS);
		}
	}

	if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) {
		treeShader->Disable();

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, 0);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, 0);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
	} else {
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_FOG);
	glDisable(GL_ALPHA_TEST);



	// clean out squares from memory that are no longer visible
	const int startClean = lastListClean * 20 % (nTrees);
	const int endClean = gs->frameNum * 20 % (nTrees);

	lastListClean = gs->frameNum;

	if (startClean > endClean) {
		for (TreeSquareStruct* pTSS = trees + startClean; pTSS < trees + nTrees; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
		for (TreeSquareStruct* pTSS = trees; pTSS < trees + endClean; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
	} else {
		for (TreeSquareStruct* pTSS = trees + startClean; pTSS < trees + endClean; ++pTSS) {
			if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->displist) {
				glDeleteLists(pTSS->displist, 1);
				pTSS->displist = 0;
			}
			if ((pTSS->lastSeenFar < gs->frameNum - 50) && pTSS->farDisplist) {
				glDeleteLists(pTSS->farDisplist, 1);
				pTSS->farDisplist = 0;
			}
		}
	}

	#undef L
}
예제 #20
0
void CAdvTreeDrawer::DrawShadowPass(void)
{
	const float treeDistance = oldTreeDistance;
	const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0] : treeGen->farTex[1];
	const bool drawDetailed = (treeDistance >= 4.0f);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, activeFarTex);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_ALPHA_TEST);
	glDisable(GL_CULL_FACE);

	glPolygonOffset(1, 1);
	glEnable(GL_POLYGON_OFFSET_FILL);

	CAdvTreeSquareDrawer_SP drawer;
	const int cx = drawer.cx = (int)(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE));
	const int cy = drawer.cy = (int)(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE));

	drawer.drawDetailed = drawDetailed;
	drawer.td = this;
	drawer.treeDistance = treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE;

	Shader::IProgramObject* po = NULL;

	GML_STDMUTEX_LOCK(tree); // DrawShadowPass

	// draw with extraSize=1
	readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer, 1);

	if (drawDetailed) {
		const int xstart = std::max(                              0, cx - 2);
		const int xend   = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2);
		const int ystart = std::max(                              0, cy - 2);
		const int yend   = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2);

		glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
		glEnable(GL_TEXTURE_2D);

		po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_NEAR);
		po->Enable();

		if (globalRendering->haveGLSL) {
			po->SetUniform3fv(1, &camera->right[0]);
			po->SetUniform3fv(2, &camera->up[0]);
		} else {
			po->SetUniformTarget(GL_VERTEX_PROGRAM_ARB);
			po->SetUniform4f(13, camera->right.x, camera->right.y, camera->right.z, 0.0f);
			po->SetUniform4f(9,  camera->up.x,    camera->up.y,    camera->up.z,    0.0f);
			po->SetUniform4f(11, 1.0f, 1.0f, 1.0f, 0.85f                           );
			po->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT));   // w = alpha/height modifier
		}

		glAlphaFunc(GL_GREATER, 0.5f);
		glEnable(GL_ALPHA_TEST);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		varr = GetVertexArray();
		varr->Initialize();

		static FadeTree fadeTrees[3000];
		FadeTree* pFT = fadeTrees;

		for (TreeSquareStruct* pTSS = trees + ystart * treesX; pTSS <= trees + yend * treesX; pTSS += treesX) {
			for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) {
				tss->lastSeen = gs->frameNum;
				varr->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes

				for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) {
					const TreeStruct* ts = &ti->second;
					const float3 pos(ts->pos);

					if (!camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2 + 150)) {
						continue;
					}

					const float camDist = (pos - camera->pos).SqLength();
					int type = ts->type;
					float dy = 0.0f;
					unsigned int displist;

					if (type < 8) {
						dy = 0.5f;
						displist = treeGen->pineDL + type;
					} else {
						type -= 8;
						dy = 0;
						displist = treeGen->leafDL + type;
					}

					if (camDist < SQUARE_SIZE * SQUARE_SIZE * 110 * 110) {
						po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
					} else if (camDist < SQUARE_SIZE * SQUARE_SIZE * 125 * 125) {
						const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15);

						glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f);
						po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z);
						glCallList(displist);
						glAlphaFunc(GL_GREATER, 0.5f);

						pFT->pos = pos;
						pFT->deltaY = dy;
						pFT->type = type;
						pFT->relDist = relDist;
						++pFT;
					} else {
						DrawTreeVertex(varr, pos, type * 0.125f, dy, false);
					}
				}
			}
		}


		po->SetUniform3f((globalRendering->haveGLSL? 3: 10), 0.0f, 0.0f, 0.0f);

		for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) {
			const float3 pos = fti->pos - UpVector * (fti->fallPos * 20);

			if (camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2)) {
				const float ang = fti->fallPos * PI;

				const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang));
				const float3 zvec((yvec.cross(float3(1.0f, 0.0f, 0.0f))).ANormalize());
				const float3 xvec(zvec.cross(yvec));

				CMatrix44f transMatrix(pos, xvec, yvec, zvec);

				glPushMatrix();
				glMultMatrixf(&transMatrix[0]);

				int type = fti->type;
				int displist;

				if (type < 8) {
					displist = treeGen->pineDL + type;
				} else {
					type -= 8;
					displist = treeGen->leafDL + type;
				}

				glCallList(displist);
				glPopMatrix();
			}
		}

		po->Disable();
		po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_FAR);
		po->Enable();

		glBindTexture(GL_TEXTURE_2D, activeFarTex);
		varr->DrawArrayT(GL_QUADS);

		for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) {
			// faded close trees
			varr = GetVertexArray();
			varr->Initialize();
			varr->CheckInitSize(12 * VA_SIZE_T);

			DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false);

			glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f));
			varr->DrawArrayT(GL_QUADS);
		}

		po->Disable();
	}

	glEnable(GL_CULL_FACE);
	glDisable(GL_POLYGON_OFFSET_FILL);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
}