bool C4LandscapeRenderGL::LoadShader(C4GroupSet *pGroups, C4Shader& shader, const char* name, int ssc) { // Setup #defines shader.AddDefine("OPENCLONK"); shader.AddDefine("OC_LANDSCAPE"); if(ssc & C4SSC_LIGHT) shader.AddDefine("OC_DYNAMIC_LIGHT"); // sample light from light texture // Create vertex shader shader.LoadVertexSlices(pGroups, "LandscapeVertexShader.glsl"); // Then load slices for fragment shader shader.LoadFragmentSlices(pGroups, "CommonShader.glsl"); shader.LoadFragmentSlices(pGroups, "LandscapeShader.glsl"); // Make attribute name map const char* AttributeNames[C4LRA_Count + 1]; AttributeNames[C4LRA_Position] = "oc_Position"; AttributeNames[C4LRA_LandscapeTexCoord] = "oc_LandscapeTexCoord"; AttributeNames[C4LRA_LightTexCoord] = "oc_LightTexCoord"; // unused if no dynamic light AttributeNames[C4LRA_Count] = NULL; // Initialise! if (!shader.Init(name, UniformNames, AttributeNames)) { shader.ClearSlices(); return false; } return true; }
virtual void AddShaderSlices(C4Shader& shader, int ssc) { #ifndef USE_CONSOLE // Add mesh-independent slices shader.AddDefine("OPENCLONK"); shader.AddDefine("OC_MESH"); if (ssc & C4SSC_MOD2) shader.AddDefine("OC_CLRMOD_MOD2"); if (ssc & C4SSC_LIGHT) shader.AddDefine("OC_DYNAMIC_LIGHT"); // Note these are never set for meshes at the moment: if (ssc & C4SSC_BASE) shader.AddDefine("OC_HAVE_BASE"); if (ssc & C4SSC_OVERLAY) shader.AddDefine("OC_HAVE_OVERLAY"); shader.LoadFragmentSlices(&::GraphicsResource.Files, "CommonShader.glsl"); shader.LoadFragmentSlices(&::GraphicsResource.Files, "ObjectShader.glsl"); #endif }
bool C4FoWRegion::Render(const C4TargetFacet *pOnScreen) { #ifndef USE_CONSOLE // Update FoW at interesting location pFoW->Update(Region, pPlayer); // On screen? No need to set up frame buffer - simply shortcut if (pOnScreen) { pFoW->Render(this, pOnScreen, pPlayer, pGL->GetProjectionMatrix()); return true; } // Set up shader. If this one doesn't work, we're really in trouble. C4Shader *pShader = pFoW->GetFramebufShader(); assert(pShader); if (!pShader) return false; // Create & bind the frame buffer pDraw->StorePrimaryClipper(); if(!BindFramebuf()) { pDraw->RestorePrimaryClipper(); return false; } assert(pSurface && hFrameBufDraw); if (!pSurface || !hFrameBufDraw) return false; // Set up a clean context glViewport(0, 0, pSurface->Wdt, pSurface->Hgt); const StdProjectionMatrix projectionMatrix = StdProjectionMatrix::Orthographic(0.0f, pSurface->Wdt, pSurface->Hgt, 0.0f); // Clear texture contents assert(pSurface->Hgt % 2 == 0); glScissor(0, pSurface->Hgt / 2, pSurface->Wdt, pSurface->Hgt / 2); glClearColor(0.0f, 0.5f / 1.5f, 0.5f / 1.5f, 0.0f); glEnable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); // clear lower half of texture glScissor(0, 0, pSurface->Wdt, pSurface->Hgt / 2); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); // Render FoW to frame buffer object glBlendFunc(GL_ONE, GL_ONE); pFoW->Render(this, NULL, pPlayer, projectionMatrix); // Copy over the old state if (OldRegion.Wdt > 0) { // How much the borders have moved int dx0 = Region.x - OldRegion.x, dy0 = Region.y - OldRegion.y, dx1 = Region.x + Region.Wdt - OldRegion.x - OldRegion.Wdt, dy1 = Region.y + Region.Hgt - OldRegion.y - OldRegion.Hgt; // Source and target rect coordinates (landscape coordinate system) int sx0 = std::max(0, dx0), sy0 = std::max(0, dy0), sx1 = OldRegion.Wdt - std::max(0, -dx1), sy1 = OldRegion.Hgt - std::max(0, -dy1), tx0 = std::max(0, -dx0), ty0 = std::max(0, -dy0), tx1 = Region.Wdt - std::max(0, dx1), ty1 = Region.Hgt - std::max(0, dy1); // Quad coordinates float vtxData[16]; float* squad = &vtxData[0]; float* tquad = &vtxData[8]; squad[0] = float(sx0); squad[1] = float(sy0); squad[2] = float(sx0); squad[3] = float(sy1); squad[4] = float(sx1); squad[5] = float(sy0); squad[6] = float(sx1); squad[7] = float(sy1); tquad[0] = float(tx0); tquad[1] = float(ty0); tquad[2] = float(tx0); tquad[3] = float(ty1); tquad[4] = float(tx1); tquad[5] = float(ty0); tquad[6] = float(tx1); tquad[7] = float(ty1); // Transform into texture coordinates for (int i = 0; i < 4; i++) { squad[i*2] = squad[i*2] / pBackSurface->Wdt; squad[i*2+1] = 1.0 - squad[i*2+1] / pBackSurface->Hgt; } // Load coordinates into vertex buffer if (hVBO == 0) { glGenBuffers(1, &hVBO); glBindBuffer(GL_ARRAY_BUFFER, hVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vtxData), vtxData, GL_STREAM_DRAW); assert(vaoid == 0); vaoid = pGL->GenVAOID(); } else { glBindBuffer(GL_ARRAY_BUFFER, hVBO); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vtxData), vtxData); } // Copy using shader C4ShaderCall Call(pShader); Call.Start(); if (Call.AllocTexUnit(C4FoWFSU_Texture)) glBindTexture(GL_TEXTURE_2D, pBackSurface->texture->texName); Call.SetUniformMatrix4x4(C4FoWFSU_ProjectionMatrix, projectionMatrix); glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR); float normalBlend = 1.0f / 4.0f, // Normals change quickly brightBlend = 1.0f / 16.0f; // Intensity more slowly glBlendColor(0.0f,normalBlend,normalBlend,brightBlend); GLuint vao; const bool has_vao = pGL->GetVAO(vaoid, vao); glBindVertexArray(vao); if (!has_vao) { glEnableVertexAttribArray(pShader->GetAttribute(C4FoWFSA_Position)); glEnableVertexAttribArray(pShader->GetAttribute(C4FoWFSA_TexCoord)); glVertexAttribPointer(pShader->GetAttribute(C4FoWFSA_Position), 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const uint8_t*>(8 * sizeof(float))); glVertexAttribPointer(pShader->GetAttribute(C4FoWFSA_TexCoord), 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const uint8_t*>(0)); } glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); Call.Finish(); } // Done! glBindFramebuffer(GL_FRAMEBUFFER, 0); pDraw->RestorePrimaryClipper(); OldRegion = Region; #endif return true; }
bool CStdGL::PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices) { const char* uniformNames[C4SSU_Count + 1]; uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix"; uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix"; uniformNames[C4SSU_NormalMatrix] = "normalMatrix"; uniformNames[C4SSU_ClrMod] = "clrMod"; uniformNames[C4SSU_Gamma] = "gamma"; uniformNames[C4SSU_BaseTex] = "baseTex"; uniformNames[C4SSU_OverlayTex] = "overlayTex"; uniformNames[C4SSU_OverlayClr] = "overlayClr"; uniformNames[C4SSU_LightTex] = "lightTex"; uniformNames[C4SSU_LightTransform] = "lightTransform"; uniformNames[C4SSU_NormalTex] = "normalTex"; uniformNames[C4SSU_AmbientTex] = "ambientTex"; uniformNames[C4SSU_AmbientTransform] = "ambientTransform"; uniformNames[C4SSU_AmbientBrightness] = "ambientBrightness"; uniformNames[C4SSU_MaterialAmbient] = "materialAmbient"; // unused uniformNames[C4SSU_MaterialDiffuse] = "materialDiffuse"; // unused uniformNames[C4SSU_MaterialSpecular] = "materialSpecular"; // unused uniformNames[C4SSU_MaterialEmission] = "materialEmission"; // unused uniformNames[C4SSU_MaterialShininess] = "materialShininess"; // unused uniformNames[C4SSU_Bones] = "bones"; // unused uniformNames[C4SSU_CullMode] = "cullMode"; // unused uniformNames[C4SSU_FrameCounter] = "frameCounter"; uniformNames[C4SSU_Count] = NULL; const char* attributeNames[C4SSA_Count + 1]; attributeNames[C4SSA_Position] = "oc_Position"; attributeNames[C4SSA_Normal] = "oc_Normal"; // unused attributeNames[C4SSA_TexCoord] = "oc_TexCoord"; // only used if C4SSC_Base is set attributeNames[C4SSA_Color] = "oc_Color"; attributeNames[C4SSA_BoneIndices0] = "oc_BoneIndices0"; // unused attributeNames[C4SSA_BoneIndices1] = "oc_BoneIndices1"; // unused attributeNames[C4SSA_BoneWeights0] = "oc_BoneWeights0"; // unused attributeNames[C4SSA_BoneWeights1] = "oc_BoneWeights1"; // unused attributeNames[C4SSA_Count] = NULL; // Clear previous content shader.Clear(); shader.ClearSlices(); // Start with #defines shader.AddDefine("OPENCLONK"); shader.AddDefine("OC_SPRITE"); if (ssc & C4SSC_MOD2) shader.AddDefine("OC_CLRMOD_MOD2"); if (ssc & C4SSC_NORMAL) shader.AddDefine("OC_WITH_NORMALMAP"); if (ssc & C4SSC_LIGHT) shader.AddDefine("OC_DYNAMIC_LIGHT"); if (ssc & C4SSC_BASE) shader.AddDefine("OC_HAVE_BASE"); if (ssc & C4SSC_OVERLAY) shader.AddDefine("OC_HAVE_OVERLAY"); if (additionalDefines) for (const char* const* define = additionalDefines; *define != NULL; ++define) shader.AddDefine(*define); // Then load slices for fragment and vertex shader shader.LoadVertexSlices(pGroups, "SpriteVertexShader.glsl"); shader.LoadFragmentSlices(pGroups, "CommonShader.glsl"); shader.LoadFragmentSlices(pGroups, "ObjectShader.glsl"); if (additionalSlices) for (const char* const* slice = additionalSlices; *slice != NULL; ++slice) shader.LoadFragmentSlices(pGroups, *slice); if (!shader.Init(name, uniformNames, attributeNames)) { shader.ClearSlices(); return false; } return true; }