void CShadowHandler::CreateShadows() { // NOTE: // we unbind later in WorldDrawer::GenerateIBLTextures() to save render // context switches (which are one of the slowest OpenGL operations!) // together with VP restoration fb.Bind(); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); CCamera* prvCam = CCamera::GetSetActiveCamera(CCamera::CAMTYPE_SHADOW); CCamera* curCam = CCamera::GetActiveCamera(); SetShadowMapSizeFactors(); SetShadowMatrix(prvCam, curCam); SetShadowCamera(curCam); if (globalRendering->haveARB) { // set the shadow-parameter registers // NOTE: so long as any part of Spring rendering still uses // ARB programs at run-time, these lines can not be removed // (all ARB programs share the same environment) glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 16, shadowTexProjCenter.x, shadowTexProjCenter.y, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 17, shadowTexProjCenter.z, shadowTexProjCenter.z, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 18, shadowTexProjCenter.w, shadowTexProjCenter.w, 0.0f, 0.0f); } if (globalRendering->haveGLSL) { for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) { shadowGenProgs[i]->Enable(); shadowGenProgs[i]->SetUniform4fv(0, &shadowTexProjCenter.x); shadowGenProgs[i]->Disable(); } } if ((sky->GetLight())->GetLightIntensity() > 0.0f) DrawShadowPasses(); CCamera::SetActiveCamera(prvCam->GetCamType()); prvCam->Update(); glShadeModel(GL_SMOOTH); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
void CShadowHandler::CreateShadows(void) { fb.Bind(); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glColor4f(1, 1, 1, 1); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glViewport(0,0,shadowMapSize,shadowMapSize); //glClearColor(0, 0, 0, 0); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); firstDraw=false; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,0,-1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float3 sundir=mapInfo->light.sunDir; cross1=(sundir.cross(UpVector)).ANormalize(); cross2=cross1.cross(sundir); centerPos=camera->pos; // centerPos.x=((int)((centerPos.x+4)/8))*8; // centerPos.y=((int)((centerPos.y+4)/8))*8; // centerPos.z=((int)((centerPos.z+4)/8))*8; // centerPos.y=(ground->GetHeight(centerPos.x,centerPos.z)); CalcMinMaxView(); //it should be possible to tweak a bit more shadow map resolution from this float maxLength=12000; float maxLengthX=(x2-x1)*1.5f; float maxLengthY=(y2-y1)*1.5f; xmid=1-(sqrt(fabs(x2))/(sqrt(fabs(x2))+sqrt(fabs(x1)))); ymid=1-(sqrt(fabs(y2))/(sqrt(fabs(y2))+sqrt(fabs(y1)))); //logOutput.Print("%.0f %.0f %.2f %.0f",y1,y2,ymid,maxLengthY); shadowMatrix[0]=cross1.x/maxLengthX; shadowMatrix[4]=cross1.y/maxLengthX; shadowMatrix[8]=cross1.z/maxLengthX; shadowMatrix[12]=-(cross1.dot(centerPos))/maxLengthX; shadowMatrix[1]=cross2.x/maxLengthY; shadowMatrix[5]=cross2.y/maxLengthY; shadowMatrix[9]=cross2.z/maxLengthY; shadowMatrix[13]=-(cross2.dot(centerPos))/maxLengthY; shadowMatrix[2]=-sundir.x/maxLength; shadowMatrix[6]=-sundir.y/maxLength; shadowMatrix[10]=-sundir.z/maxLength; shadowMatrix[14]=(centerPos.x*sundir.x+centerPos.z*sundir.z)/maxLength+0.5f; glLoadMatrixf(shadowMatrix.m); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,16, xmid,ymid,0,0); //these registers should not be overwritten by anything GetShadowMapSizeFactors(p17, p18); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,17, p17,p17,0.0f,0.0f); //these registers should not be overwritten by anything glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,18, p18,p18,0.0f,0.0f); //these registers should not be overwritten by anything float3 oldup=camera->up; camera->right=shadowHandler->cross1; camera->up=shadowHandler->cross2; camera->pos2=camera->pos+sundir*8000; DrawShadowPasses(); camera->up=oldup; camera->pos2=camera->pos; shadowMatrix[14]-=0.00001f; glShadeModel(GL_SMOOTH); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); fb.Unbind(); glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY); }
void CShadowHandler::CreateShadows() { fb.Bind(); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glViewport(0, 0, shadowMapSize, shadowMapSize); // glClearColor(0, 0, 0, 0); // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, 0, -1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); const ISkyLight* L = sky->GetLight(); // sun direction is in world-space, invert it sunDirZ = -L->GetLightDir(); sunDirX = (sunDirZ.cross(UpVector)).ANormalize(); sunDirY = (sunDirX.cross(sunDirZ)).ANormalize(); SetShadowMapSizeFactors(); // NOTE: // the xy-scaling factors from CalcMinMaxView do not change linearly // or smoothly with camera movements, creating visible artefacts (eg. // large jumps in shadow resolution) // // therefore, EITHER use "fixed" scaling values such that the entire // map barely fits into the sun's frustum (by pretending it is embedded // in a sphere and taking its diameter), OR variable scaling such that // everything that can be seen by the camera maximally fills the sun's // frustum (choice of projection-style is left to the user and can be // changed at run-time) // // the first option means larger maps will have more blurred/aliased // shadows if the depth buffer is kept at the same size, but no (map) // geometry is ever omitted // // the second option means shadows have higher average resolution, but // become less sharp as the viewing volume increases (through eg.camera // rotations) and geometry can be omitted in some cases // // NOTE: // when DynamicSun is enabled, the orbit is always circular in the xz // plane, instead of elliptical when the map has an aspect-ratio != 1 // const float xyScale = GetShadowProjectionRadius(camera, centerPos, -sunDirZ); const float xScale = xyScale; const float yScale = xyScale; const float zScale = globalRendering->viewRange; shadowMatrix[ 0] = sunDirX.x / xScale; shadowMatrix[ 1] = sunDirY.x / yScale; shadowMatrix[ 2] = sunDirZ.x / zScale; shadowMatrix[ 4] = sunDirX.y / xScale; shadowMatrix[ 5] = sunDirY.y / yScale; shadowMatrix[ 6] = sunDirZ.y / zScale; shadowMatrix[ 8] = sunDirX.z / xScale; shadowMatrix[ 9] = sunDirY.z / yScale; shadowMatrix[10] = sunDirZ.z / zScale; // rotate the target position into sun-space for the translation shadowMatrix[12] = (-sunDirX.dot(centerPos) / xScale); shadowMatrix[13] = (-sunDirY.dot(centerPos) / yScale); shadowMatrix[14] = (-sunDirZ.dot(centerPos) / zScale) + 0.5f; glLoadMatrixf(shadowMatrix.m); // set the shadow-parameter registers // NOTE: so long as any part of Spring rendering still uses // ARB programs at run-time, these lines can not be removed // (all ARB programs share the same environment) glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 16, shadowTexProjCenter.x, shadowTexProjCenter.y, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 17, shadowTexProjCenter.z, shadowTexProjCenter.z, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 18, shadowTexProjCenter.w, shadowTexProjCenter.w, 0.0f, 0.0f); if (globalRendering->haveGLSL) { for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) { shadowGenProgs[i]->Enable(); shadowGenProgs[i]->SetUniform4fv(0, &shadowTexProjCenter.x); shadowGenProgs[i]->Disable(); } } if (L->GetLightIntensity() > 0.0f) { // move view into sun-space const float3 oldup = camera->up; camera->right = sunDirX; camera->up = sunDirY; DrawShadowPasses(); camera->up = oldup; } glShadeModel(GL_SMOOTH); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // we do this later to save render context switches (this is one of the slowest opengl operations!) // fb.Unbind(); // glViewport(globalRendering->viewPosX,0,globalRendering->viewSizeX,globalRendering->viewSizeY); }
void CShadowHandler::CreateShadows(void) { fb.Bind(); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glColor4f(1, 1, 1, 1); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glViewport(0, 0, shadowMapSize, shadowMapSize); // glClearColor(0, 0, 0, 0); // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, 0, -1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); cross1 = (mapInfo->light.sunDir.cross(UpVector)).ANormalize(); cross2 = cross1.cross(mapInfo->light.sunDir); centerPos = camera->pos; //! derive the size of the shadow-map from the //! intersection points of the camera frustum //! with the xz-plane CalcMinMaxView(); SetShadowMapSizeFactors(); // it should be possible to tweak a bit more shadow map resolution from this const float maxLength = 12000.0f; const float maxLengthX = (x2 - x1) * 1.5f; const float maxLengthY = (y2 - y1) * 1.5f; #if (SHADOWMATRIX_NONLINEAR == 1) xmid = 1.0f - (sqrt(fabs(x2)) / (sqrt(fabs(x2)) + sqrt(fabs(x1)))); ymid = 1.0f - (sqrt(fabs(y2)) / (sqrt(fabs(y2)) + sqrt(fabs(y1)))); #else xmid = 0.5f; ymid = 0.5f; #endif shadowMatrix[ 0] = cross1.x / maxLengthX; shadowMatrix[ 4] = cross1.y / maxLengthX; shadowMatrix[ 8] = cross1.z / maxLengthX; shadowMatrix[12] = -(cross1.dot(centerPos)) / maxLengthX; shadowMatrix[ 1] = cross2.x / maxLengthY; shadowMatrix[ 5] = cross2.y / maxLengthY; shadowMatrix[ 9] = cross2.z / maxLengthY; shadowMatrix[13] = -(cross2.dot(centerPos)) / maxLengthY; shadowMatrix[ 2] = -mapInfo->light.sunDir.x / maxLength; shadowMatrix[ 6] = -mapInfo->light.sunDir.y / maxLength; shadowMatrix[10] = -mapInfo->light.sunDir.z / maxLength; shadowMatrix[14] = ((centerPos.x * mapInfo->light.sunDir.x + centerPos.z * mapInfo->light.sunDir.z) / maxLength) + 0.5f; glLoadMatrixf(shadowMatrix.m); //! set the shadow-parameter registers //! NOTE: so long as any part of Spring rendering still uses //! ARB programs at run-time, these lines can not be removed //! (all ARB programs share the same environment) glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 16, xmid, ymid, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 17, p17, p17, 0.0f, 0.0f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 18, p18, p18, 0.0f, 0.0f); if (globalRendering->haveGLSL) { for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) { shadowGenProgs[i]->Enable(); shadowGenProgs[i]->SetUniform4f(0, xmid, ymid, p17, p18); shadowGenProgs[i]->Disable(); } } //! move view into sun-space float3 oldup = camera->up; camera->right = cross1; camera->up = cross2; camera->pos2 = camera->pos + mapInfo->light.sunDir * 8000; DrawShadowPasses(); camera->up = oldup; camera->pos2 = camera->pos; shadowMatrix[14] -= 0.00001f; glShadeModel(GL_SMOOTH); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); //we do this later to save render context switches (this is one of the slowest opengl operations!) //fb.Unbind(); //glViewport(globalRendering->viewPosX,0,globalRendering->viewSizeX,globalRendering->viewSizeY); }