Skip to content

Commit

Permalink
fix #2855 #5092 #5180
Browse files Browse the repository at this point in the history
  • Loading branch information
rt committed Jun 26, 2017
1 parent b95799f commit 7a3c89d
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 51 deletions.
19 changes: 16 additions & 3 deletions cont/base/springcontent/shaders/GLSL/ShadowGenFragProg.glsl
@@ -1,12 +1,25 @@
uniform sampler2D alphaMaskTex;

varying vec4 vertexShadowClipPos;
uniform vec4 shadowParams;
uniform vec2 alphaParams;

varying mat4 shadowViewMat;
varying mat4 shadowProjMat;
varying vec4 vertexModelPos;


void main() {
if (texture2D(alphaMaskTex, gl_TexCoord[0].st).a <= 0.5)
if (texture2D(alphaMaskTex, gl_TexCoord[0].st).a <= alphaParams.x)
discard;

#if 0
#if 1
// note: voids the glPolygonOffset calls
vec4 vertexShadowPos = shadowViewMat * vertexModelPos;
vertexShadowPos.xy *= (inversesqrt(abs(vertexShadowPos.xy) + shadowParams.zz) + shadowParams.ww);
vertexShadowPos.xy += shadowParams.xy;
vertexShadowPos.z += 0.00250;
vec4 vertexShadowClipPos = shadowProjMat * vertexShadowPos;

float nearDepth = gl_DepthRange.near;
float farDepth = gl_DepthRange.far;
float depthRange = gl_DepthRange.diff; // far - near
Expand Down
16 changes: 14 additions & 2 deletions cont/base/springcontent/shaders/GLSL/ShadowGenVertProg.glsl
Expand Up @@ -8,7 +8,12 @@ uniform vec3 treeOffset;
#define MAX_TREE_HEIGHT 60.0
#endif

varying vec4 vertexShadowClipPos;
#ifdef SHADOWGEN_PROGRAM_MAP
varying mat4 shadowViewMat;
varying mat4 shadowProjMat;
varying vec4 vertexModelPos;
#endif


void main() {
#ifdef SHADOWGEN_PROGRAM_TREE_NEAR
Expand All @@ -17,12 +22,19 @@ void main() {
vec3 offsetVec = vec3(0.0, 0.0, 0.0);
#endif


#ifdef SHADOWGEN_PROGRAM_MAP
shadowViewMat = gl_ModelViewMatrix;
shadowProjMat = gl_ProjectionMatrix;
vertexModelPos = gl_Vertex + vec4(offsetVec, 0.0);
#endif

vec4 vertexPos = gl_Vertex + vec4(offsetVec, 0.0);
vec4 vertexShadowPos = gl_ModelViewMatrix * vertexPos;
vertexShadowPos.xy *= (inversesqrt(abs(vertexShadowPos.xy) + shadowParams.zz) + shadowParams.ww);
vertexShadowPos.xy += shadowParams.xy;

gl_Position = vertexShadowClipPos = gl_ProjectionMatrix * vertexShadowPos;
gl_Position = gl_ProjectionMatrix * vertexShadowPos;


#ifdef SHADOWGEN_PROGRAM_MODEL
Expand Down
19 changes: 19 additions & 0 deletions rts/Game/UnsyncedGameCommands.cpp
Expand Up @@ -314,6 +314,24 @@ class ShadowsActionExecutor : public IUnsyncedActionExecutor {
}
};

class MapShadowPolyOffsetActionExecutor: public IUnsyncedActionExecutor {
public:
MapShadowPolyOffsetActionExecutor(): IUnsyncedActionExecutor("MapShadowPolyOffset", "") {}

bool Execute(const UnsyncedAction& action) const {
std::istringstream buf(action.GetArgs() + " 0.0 0.0");

float& pofs = (readMap->GetGroundDrawer())->spPolygonOffsetScale;
float& pofu = (readMap->GetGroundDrawer())->spPolygonOffsetUnits;

buf >> pofs;
buf >> pofu;

LOG("MapShadowPolygonOffset{Scale,Units}={%f,%f}", pofs, pofu);
return true;
}
};



class WaterActionExecutor : public IUnsyncedActionExecutor {
Expand Down Expand Up @@ -3056,6 +3074,7 @@ void UnsyncedGameCommands::AddDefaultActionExecutors() {
AddActionExecutor(new SelectCycleActionExecutor());
AddActionExecutor(new DeselectActionExecutor());
AddActionExecutor(new ShadowsActionExecutor());
AddActionExecutor(new MapShadowPolyOffsetActionExecutor());
AddActionExecutor(new MapMeshDrawerActionExecutor());
AddActionExecutor(new MapBorderActionExecutor());
AddActionExecutor(new WaterActionExecutor());
Expand Down
3 changes: 3 additions & 0 deletions rts/Map/BaseGroundDrawer.h
Expand Up @@ -65,6 +65,9 @@ class CBaseGroundDrawer
float LODScaleRefraction;
float LODScaleTerrainReflection;

float spPolygonOffsetScale = -1.0f;
float spPolygonOffsetUnits = -1.0f;

int jamColor[3];
int losColor[3];
int radarColor[3];
Expand Down
10 changes: 5 additions & 5 deletions rts/Map/SMF/SMFGroundDrawer.cpp
Expand Up @@ -427,9 +427,8 @@ void CSMFGroundDrawer::DrawBorder(const DrawPass::e drawPass)

glEnable(GL_BLEND);

if (wireframe) {
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

/*
if (mapRendering->voidWater && (drawPass != DrawPass::WaterReflection)) {
Expand All @@ -446,9 +445,8 @@ void CSMFGroundDrawer::DrawBorder(const DrawPass::e drawPass)
}
*/

if (wireframe) {
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

glDisable(GL_BLEND);

Expand Down Expand Up @@ -477,10 +475,12 @@ void CSMFGroundDrawer::DrawShadowPass()
Shader::IProgramObject* po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_MAP);

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

glPolygonOffset(-1.0f, -1.0f);
// also render the border geometry to prevent light-visible backfaces
po->Enable();
meshDrawer->DrawMesh(DrawPass::Shadow);
meshDrawer->DrawBorderMesh(DrawPass::Shadow);
po->Disable();

glDisable(GL_POLYGON_OFFSET_FILL);
Expand Down
29 changes: 13 additions & 16 deletions rts/Rendering/Shaders/ShaderHandler.cpp
Expand Up @@ -95,32 +95,30 @@ Shader::IProgramObject* CShaderHandler::GetProgramObject(const std::string& poCl

Shader::IProgramObject* CShaderHandler::CreateProgramObject(const std::string& poClass, const std::string& poName, bool arbProgram) {
Shader::IProgramObject* po = Shader::nullProgramObject;
const char* poType = arbProgram? "ARB": "GLSL";

if (programObjects.find(poClass) != programObjects.end()) {
if (programObjects[poClass].find(poName) != programObjects[poClass].end()) {
LOG_L(L_WARNING, "[%s] There is already a shader program named \"%s\"!",
__FUNCTION__, poName.c_str());
LOG_L(L_WARNING, "[SH::%s] program-object \"%s\" already exists", __func__, poName.c_str());
return (programObjects[poClass][poName]);
}
} else {
programObjects[poClass] = ProgramObjMap();
}

if (arbProgram) {
if (globalRendering->haveARB) {
if (globalRendering->haveARB)
po = new Shader::ARBProgramObject(poName);
}

} else {
if (globalRendering->haveGLSL) {
if (globalRendering->haveGLSL)
po = new Shader::GLSLProgramObject(poName);
}
}

if (po == Shader::nullProgramObject) {
LOG_L(L_ERROR, "[%s] Tried to create \"%s\" a %s shader program on hardware w/o support for it!",
__FUNCTION__, poName.c_str(), arbProgram ? "ARB" : "GLSL");
}

if (po == Shader::nullProgramObject)
LOG_L(L_ERROR, "[SH::%s] hardware does not support creating (%s) program-object \"%s\"", __func__, poType, poName.c_str());

programObjects[poClass][poName] = po;
return po;
}
Expand All @@ -136,24 +134,23 @@ Shader::IShaderObject* CShaderHandler::CreateShaderObject(const std::string& soN
case GL_FRAGMENT_PROGRAM_ARB: {
// assert(StringToLower(soName).find("arb") != std::string::npos);

if (globalRendering->haveARB) {
if (globalRendering->haveARB)
so = new Shader::ARBShaderObject(soType, soName);
}

} break;

default: {
// assume GLSL shaders by default
// assert(StringToLower(soName).find("arb") == std::string::npos);

if (globalRendering->haveGLSL) {
if (globalRendering->haveGLSL)
so = new Shader::GLSLShaderObject(soType, soName, soDefs);
}

} break;
}

if (so == Shader::nullShaderObject) {
LOG_L(L_ERROR, "[%s] Tried to create a shader (\"%s\") on hardware that does not support them!",
__FUNCTION__, soName.c_str());
LOG_L(L_ERROR, "[SH::%s] hardware does not support creating shader-object \"%s\"", __func__, soName.c_str());
return so;
}

Expand Down
32 changes: 21 additions & 11 deletions rts/Rendering/ShadowHandler.cpp
Expand Up @@ -211,19 +211,24 @@ void CShadowHandler::LoadShadowGenShaderProgs()
if (globalRendering->haveGLSL) {
for (int i = 0; i < SHADOWGEN_PROGRAM_LAST; i++) {
Shader::IProgramObject* po = sh->CreateProgramObject("[ShadowHandler]", shadowGenProgHandles[i] + "GLSL", false);
Shader::IShaderObject* vso = sh->CreateShaderObject("GLSL/ShadowGenVertProg.glsl", shadowGenProgDefines[i] + extraDef, GL_VERTEX_SHADER);
// Shader::IShaderObject* fso = sh->CreateShaderObject("GLSL/ShadowGenFragProg.glsl", shadowGenProgDefines[i] + extraDef, GL_FRAGMENT_SHADER);

po->AttachShaderObject(vso);
// po->AttachShaderObject(fso);
if (i == SHADOWGEN_PROGRAM_MAP) {
po->AttachShaderObject(sh->CreateShaderObject("GLSL/ShadowGenVertProg.glsl", shadowGenProgDefines[i] + extraDef, GL_VERTEX_SHADER));
po->AttachShaderObject(sh->CreateShaderObject("GLSL/ShadowGenFragProg.glsl", shadowGenProgDefines[i] + extraDef, GL_FRAGMENT_SHADER));
} else {
po->AttachShaderObject(sh->CreateShaderObject("GLSL/ShadowGenVertProg.glsl", shadowGenProgDefines[i] + extraDef, GL_VERTEX_SHADER));
}

po->Link();
po->SetUniformLocation("shadowParams"); // idx 0
po->SetUniformLocation("cameraDirX"); // idx 1, used by SHADOWGEN_PROGRAM_TREE_NEAR
po->SetUniformLocation("cameraDirY"); // idx 2, used by SHADOWGEN_PROGRAM_TREE_NEAR
po->SetUniformLocation("treeOffset"); // idx 3, used by SHADOWGEN_PROGRAM_TREE_NEAR
po->SetUniformLocation("alphaMaskTex"); // idx 4
po->SetUniformLocation("alphaParams"); // idx 5, used by SHADOWGEN_PROGRAM_MAP
po->Enable();
po->SetUniform1i(4, 0); // alphaMaskTex
po->SetUniform2f(5, mapInfo->map.voidAlphaMin, 0.0f); // alphaParams
po->Disable();
po->Validate();

Expand Down Expand Up @@ -356,8 +361,8 @@ void CShadowHandler::DrawShadowPasses()

glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT);
glEnable(GL_CULL_FACE);

glCullFace(GL_BACK);

eventHandler.DrawWorldShadow();

if ((shadowGenBits & SHADOWGEN_BIT_TREE) != 0) {
Expand All @@ -373,14 +378,19 @@ void CShadowHandler::DrawShadowPasses()
featureDrawer->DrawShadowPass();
}

glCullFace(GL_FRONT);
// cull front-faces during the terrain shadow pass: sun direction
// can be set so oblique that geometry back-faces are visible (eg.
// from hills near map edges) from its POV
// (could just disable culling of terrain faces, but we also want
// to prevent overdraw in such low-angle passes)
// cull front-faces during the terrain shadow pass: sun direction
// can be set so oblique that geometry back-faces are visible (eg.
// from hills near map edges) from its POV
//
// not the best idea, causes acne when projecting the shadow-map
// (rasterizing back-faces writes different depth values) and is
// no longer required since border geometry will fully hide them
// (could just disable culling of terrain faces entirely, but we
// also want to prevent overdraw in low-angle passes)
// glCullFace(GL_FRONT);
if ((shadowGenBits & SHADOWGEN_BIT_MAP) != 0)
readMap->GetGroundDrawer()->DrawShadowPass();

glPopAttrib();

inShadowPass = false;
Expand Down
44 changes: 30 additions & 14 deletions rts/Rendering/UnitDrawer.cpp
Expand Up @@ -93,6 +93,20 @@ static const void KillShadowTex(const CS3OTextureHandler::S3OTexMat*) {
}


static const void BindShadowTexAtlas(const CS3OTextureHandler::S3OTexMat*) {
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texturehandler3DO->GetAtlasTex2ID());
}

static const void KillShadowTexAtlas(const CS3OTextureHandler::S3OTexMat*) {
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
}



static const void PushRenderState3DO() {
BindOpaqueTexAtlas(nullptr);

Expand Down Expand Up @@ -140,7 +154,7 @@ static const BindTexFunc opaqueTexBindFuncs[MODELTYPE_OTHER] = {
};

static const BindTexFunc shadowTexBindFuncs[MODELTYPE_OTHER] = {
BindShadowTexDummy, // 3DO (no-op)
BindShadowTexAtlas, // 3DO
BindShadowTex, // S3O
BindShadowTex, // OBJ
BindShadowTex, // ASS
Expand All @@ -152,7 +166,7 @@ static const BindTexFunc* bindModelTexFuncs[] = {
};

static const KillTexFunc shadowTexKillFuncs[MODELTYPE_OTHER] = {
KillShadowTexDummy, // 3DO (no-op)
KillShadowTexAtlas, // 3DO
KillShadowTex, // S3O
KillShadowTex, // OBJ
KillShadowTex, // ASS
Expand Down Expand Up @@ -377,14 +391,12 @@ void CUnitDrawer::Draw(bool drawReflection, bool drawRefraction)

// first do the deferred pass; conditional because
// most of the water renderers use their own FBO's
if (drawDeferred && !drawReflection && !drawRefraction) {
if (drawDeferred && !drawReflection && !drawRefraction)
LuaObjectDrawer::DrawDeferredPass(LUAOBJ_UNIT);
}

// now do the regular forward pass
if (drawForward) {
if (drawForward)
DrawOpaquePass(false, drawReflection, drawRefraction);
}

farTextureHandler->Draw();

Expand Down Expand Up @@ -417,10 +429,13 @@ void CUnitDrawer::DrawOpaqueUnits(int modelType, bool drawReflection, bool drawR
{
const auto& unitBin = opaqueModelRenderers[modelType]->GetUnitBin();

for (auto unitBinIt = unitBin.cbegin(); unitBinIt != unitBin.cend(); ++unitBinIt) {
BindModelTypeTexture(modelType, unitBinIt->first);
for (const auto& unitBinPair: unitBin) {
const auto& unitSet = unitBinPair.second;
const int textureType = unitBinPair.first;

BindModelTypeTexture(modelType, textureType);

for (CUnit* unit: unitBinIt->second) {
for (CUnit* unit: unitSet) {
DrawOpaqueUnit(unit, drawReflection, drawRefraction);
}
}
Expand Down Expand Up @@ -573,12 +588,13 @@ void CUnitDrawer::DrawOpaqueUnitShadow(CUnit* unit) {
void CUnitDrawer::DrawOpaqueUnitsShadow(int modelType) {
const auto& unitBin = opaqueModelRenderers[modelType]->GetUnitBin();

for (const auto& unitBinP: unitBin) {
const auto& unitSet = unitBinP.second;
const int textureType = unitBinP.first;
for (const auto& unitBinPair: unitBin) {
const auto& unitSet = unitBinPair.second;
const int textureType = unitBinPair.first;

BindModelTypeTexture(modelType, textureType);
// shadowTexBindFuncs[modelType](texturehandlerS3O->GetTexture(textureType));
// only need to bind the atlas once for 3DO's, but KISS
assert((modelType == MODELTYPE_3DO) == (textureType == -1));
shadowTexBindFuncs[modelType](texturehandlerS3O->GetTexture(textureType));

for (const auto& unitSetP: unitSet) {
DrawOpaqueUnitShadow(unitSetP);
Expand Down

0 comments on commit 7a3c89d

Please sign in to comment.