static void drawDepthOnly(const glm::mat4 &ModelViewProjection, const glm::vec4 ¶msXLight, const glm::vec4 ¶msYLight) { const auto &program = pie_ActivateShader(SHADER_TERRAIN_DEPTH, ModelViewProjection, paramsXLight, paramsYLight, 1, glm::mat4(1.f), glm::mat4(1.f)); pie_SetTexturePage(TEXPAGE_NONE); pie_SetRendMode(REND_OPAQUE); // we only draw in the depth buffer of using fog of war, as the clear color is black then if (!pie_GetFogStatus()) { glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } // draw slightly higher distance than it actually is so it will not // by accident obscure the actual terrain glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.1f, 1.0f); // bind the vertex buffer geometryIndexVBO->bind(); geometryVBO->bind(); glVertexAttribPointer(program.locVertex, 3, GL_FLOAT, GL_FALSE, sizeof(RenderVertex), BUFFER_OFFSET(0)); glEnableVertexAttribArray(program.locVertex); for (int x = 0; x < xSectors; x++) { for (int y = 0; y < ySectors; y++) { if (sectors[x * ySectors + y].draw) { addDrawRangeElements(GL_TRIANGLES, sectors[x * ySectors + y].geometryOffset, sectors[x * ySectors + y].geometryOffset + sectors[x * ySectors + y].geometrySize, sectors[x * ySectors + y].geometryIndexSize, GL_UNSIGNED_INT, sectors[x * ySectors + y].geometryIndexOffset); } } } finishDrawRangeElements(); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (!pie_GetFogStatus()) { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } // disable the depth offset glDisable(GL_POLYGON_OFFSET_FILL); glDisableVertexAttribArray(program.locVertex); pie_DeactivateShader(); }
/** * Either draw the elements or batch them to be sent to OpenGL later * This improves performance by reducing the amount of OpenGL calls. */ static void addDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLuint offset) { ASSERT(mode == GL_TRIANGLES, "not supported"); ASSERT(type == GL_UNSIGNED_INT, "not supported"); if (end - start + 1 > GLmaxElementsVertices) { debug(LOG_WARNING, "A single call provided too much vertices, will operate at reduced performance or crash. Decrease the sector size to fix this."); } if (count > GLmaxElementsIndices) { debug(LOG_WARNING, "A single call provided too much indices, will operate at reduced performance or crash. Decrease the sector size to fix this."); } if (!drawRangeElementsStarted) { dreStart = start; dreEnd = end; dreCount = count; dreOffset = offset; drawRangeElementsStarted = true; return; } // check if we can append theoretically and // check if this will not go over the bounds advised by the opengl implementation if (dreOffset + dreCount != offset || dreCount + count > GLmaxElementsIndices || end - dreStart + 1 > GLmaxElementsVertices) { finishDrawRangeElements(); // start anew addDrawRangeElements(mode, start, end, count, type, offset); } else { // OK to append dreCount += count; dreEnd = end; } // make sure we did everything right ASSERT(dreEnd - dreStart + 1 <= GLmaxElementsVertices, "too many vertices (%i)", (int)(dreEnd - dreStart + 1)); ASSERT(dreCount <= GLmaxElementsIndices, "too many indices (%i)", (int)(dreCount)); }
/** * Draw the water. */ void drawWater(const glm::mat4 &viewMatrix) { int x, y; const glm::vec4 paramsX(0, 0, -1.0f / world_coord(4), 0); const glm::vec4 paramsY(1.0f / world_coord(4), 0, 0, 0); const glm::vec4 paramsX2(0, 0, -1.0f / world_coord(5), 0); const glm::vec4 paramsY2(1.0f / world_coord(5), 0, 0, 0); const auto &renderState = getCurrentRenderState(); const auto &program = pie_ActivateShader(SHADER_WATER, viewMatrix, paramsX, paramsY, paramsX2, paramsY2, 0, 1, glm::translate(glm::vec3(waterOffset, 0.f, 0.f)), glm::mat4(1.f), renderState.fogEnabled, renderState.fogBegin, renderState.fogEnd); glDepthMask(GL_FALSE); // first texture unit pie_SetTexturePage(iV_GetTexture("page-80-water-1.png")); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // multiplicative blending pie_SetRendMode(REND_MULTIPLICATIVE); // second texture unit glActiveTexture(GL_TEXTURE1); pie_Texture(iV_GetTexture("page-81-water-2.png")).bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // bind the vertex buffer waterIndexVBO->bind(); waterVBO->bind(); glVertexAttribPointer(program.locVertex, 3, GL_FLOAT, GL_FALSE, sizeof(RenderVertex), BUFFER_OFFSET(0)); glEnableVertexAttribArray(program.locVertex); for (x = 0; x < xSectors; x++) { for (y = 0; y < ySectors; y++) { if (sectors[x * ySectors + y].draw) { addDrawRangeElements(GL_TRIANGLES, sectors[x * ySectors + y].geometryOffset, sectors[x * ySectors + y].geometryOffset + sectors[x * ySectors + y].geometrySize, sectors[x * ySectors + y].waterIndexSize, GL_UNSIGNED_INT, sectors[x * ySectors + y].waterIndexOffset); } } } finishDrawRangeElements(); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(program.locVertex); // move the water if (!gamePaused()) { waterOffset += graphicsTimeAdjustedIncrement(0.1f); } // disable second texture glActiveTexture(GL_TEXTURE0); // clean up glDepthMask(GL_TRUE); pie_DeactivateShader(); //glBindBuffer(GL_ARRAY_BUFFER, 0); // HACK Must unbind GL_ARRAY_BUFFER (don't know if it has to be unbound everywhere), otherwise text rendering may mysteriously crash. }
static void drawTerrainLayers(const glm::mat4 &ModelViewProjection, const glm::vec4 ¶msXLight, const glm::vec4 ¶msYLight, const glm::mat4 &textureMatrix) { const auto &renderState = getCurrentRenderState(); const glm::vec4 fogColor( renderState.fogColour.vector[0] / 255.f, renderState.fogColour.vector[1] / 255.f, renderState.fogColour.vector[2] / 255.f, renderState.fogColour.vector[3] / 255.f ); const auto &program = pie_ActivateShader(SHADER_TERRAIN, ModelViewProjection, glm::vec4(0.f), glm::vec4(0.f), paramsXLight, paramsYLight, 0, 1, glm::mat4(1.f), textureMatrix, renderState.fogEnabled, renderState.fogBegin, renderState.fogEnd, fogColor); // additive blending pie_SetRendMode(REND_ADDITIVE); // only draw colors glDepthMask(GL_FALSE); textureIndexVBO->bind(); // load the vertex (geometry) buffer geometryVBO->bind(); glVertexAttribPointer(program.locVertex, 3, GL_FLOAT, GL_FALSE, sizeof(RenderVertex), BUFFER_OFFSET(0)); glEnableVertexAttribArray(program.locVertex); textureVBO->bind(); ASSERT_OR_RETURN(, psGroundTypes, "Ground type was not set, no textures will be seen."); // draw each layer separately for (int layer = 0; layer < numGroundTypes; layer++) { const glm::vec4 paramsX(0, 0, -1.0f / world_coord(psGroundTypes[layer].textureSize), 0 ); const glm::vec4 paramsY(1.0f / world_coord(psGroundTypes[layer].textureSize), 0, 0, 0 ); pie_ActivateShader(SHADER_TERRAIN, ModelViewProjection, paramsX, paramsY, paramsXLight, paramsYLight, 0, 1, glm::mat4(1.f), textureMatrix, renderState.fogEnabled, renderState.fogBegin, renderState.fogEnd, fogColor); // load the texture int texPage = iV_GetTexture(psGroundTypes[layer].textureName); pie_SetTexturePage(texPage); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // load the color buffer glVertexAttribPointer(program.locColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(PIELIGHT), BUFFER_OFFSET(sizeof(PIELIGHT)*xSectors * ySectors * (sectorSize + 1) * (sectorSize + 1) * 2 * layer)); glEnableVertexAttribArray(program.locColor); for (int x = 0; x < xSectors; x++) { for (int y = 0; y < ySectors; y++) { if (sectors[x * ySectors + y].draw) { addDrawRangeElements(GL_TRIANGLES, sectors[x * ySectors + y].geometryOffset, sectors[x * ySectors + y].geometryOffset + sectors[x * ySectors + y].geometrySize, sectors[x * ySectors + y].textureIndexSize[layer], GL_UNSIGNED_INT, sectors[x * ySectors + y].textureIndexOffset[layer]); } } } finishDrawRangeElements(); } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // we don't need this one anymore glDisableVertexAttribArray(program.locVertex); glDisableVertexAttribArray(program.locColor); pie_DeactivateShader(); }