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); }
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; }
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()); }
// 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()); }
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; }
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(); }
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()); }
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; }
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); }
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(); }
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); }
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; }
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); }
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); }
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(); }
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(); } }
static void ResetDefShadowUnitDrawState(unsigned int modelType, bool deferredPass) { Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MODEL); po->Disable(); glDisable(GL_POLYGON_OFFSET_FILL); }
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); }
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 }
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); }