// Run from screen.c on init. Do not change the order of loading here! First ones are enumerated. bool pie_LoadShaders() { SHADER_PROGRAM program; int result; // Load some basic shaders memset(&program, 0, sizeof(program)); shaderProgram.append(program); // TCMask shader for map-placed models with advanced lighting debug(LOG_3D, "Loading shader: SHADER_COMPONENT"); result = pie_LoadShader("Component program", "shaders/tcmask.vert", "shaders/tcmask.frag"); ASSERT_OR_RETURN(false, result, "Failed to load component shader"); // TCMask shader for buttons with flat lighting debug(LOG_3D, "Loading shader: SHADER_BUTTON"); result = pie_LoadShader("Button program", "shaders/button.vert", "shaders/button.frag"); ASSERT_OR_RETURN(false, result, "Failed to load button shader"); currentShaderMode = SHADER_NONE; return true; }
/*! * Load shape levels recursively * \param ppFileData Pointer to the data (usualy read from a file) * \param FileDataEnd ??? * \param nlevels Number of levels to load * \return pointer to iFSDShape structure (or NULL on error) * \pre ppFileData loaded * \post s allocated */ static iIMDShape *_imd_load_level(const QString &filename, const char **ppFileData, const char *FileDataEnd, int nlevels, int pieVersion, int level) { const char *pFileData = *ppFileData; char buffer[PATH_MAX] = {'\0'}; int cnt = 0, n = 0, i; iIMDShape *s = nullptr; float dummy; if (nlevels == 0) { return nullptr; } i = sscanf(pFileData, "%255s %n", buffer, &cnt); ASSERT_OR_RETURN(nullptr, i == 1, "Bad directive following LEVEL"); s = new iIMDShape; // Optionally load and ignore deprecated MATERIALS directive if (strcmp(buffer, "MATERIALS") == 0) { i = sscanf(pFileData, "%255s %f %f %f %f %f %f %f %f %f %f%n", buffer, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &cnt); ASSERT_OR_RETURN(nullptr, i == 11, "Bad MATERIALS directive"); debug(LOG_WARNING, "MATERIALS directive no longer supported!"); pFileData += cnt; } else if (strcmp(buffer, "SHADERS") == 0) { char vertex[PATH_MAX], fragment[PATH_MAX]; if (sscanf(pFileData, "%255s %255s %255s%n", buffer, vertex, fragment, &cnt) != 3) { debug(LOG_ERROR, "%s shader corrupt: %s", filename.toUtf8().constData(), buffer); return nullptr; } std::vector<std::string> uniform_names { "colour", "teamcolour", "stretch", "tcmask", "fogEnabled", "normalmap", "specularmap", "ecmEffect", "alphaTest", "graphicsCycle", "ModelViewProjectionMatrix" }; s->shaderProgram = pie_LoadShader(filename.toUtf8().constData(), vertex, fragment, uniform_names); pFileData += cnt; } if (sscanf(pFileData, "%255s %d%n", buffer, &s->npoints, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(2): file corrupt"); return nullptr; } pFileData += cnt; // load points ASSERT_OR_RETURN(nullptr, strcmp(buffer, "POINTS") == 0, "Expecting 'POINTS' directive, got: %s", buffer); _imd_load_points(&pFileData, s); if (sscanf(pFileData, "%255s %d%n", buffer, &s->npolys, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(3): file corrupt"); return nullptr; } pFileData += cnt; ASSERT_OR_RETURN(nullptr, strcmp(buffer, "POLYGONS") == 0, "Expecting 'POLYGONS' directive, got: %s", buffer); _imd_load_polys(filename, &pFileData, s, pieVersion); // optional stuff : levels, object animations, connectors s->objanimframes = 0; while (!AtEndOfFile(pFileData, FileDataEnd)) // check for end of file (give or take white space) { // Scans in the line ... if we don't get 2 parameters then quit if (sscanf(pFileData, "%255s %d%n", buffer, &n, &cnt) != 2) { break; } pFileData += cnt; if (strcmp(buffer, "LEVEL") == 0) // check for next level { debug(LOG_3D, "imd[_load_level] = npoints %d, npolys %d", s->npoints, s->npolys); s->next = _imd_load_level(filename, &pFileData, FileDataEnd, nlevels - 1, pieVersion, level + 1); } else if (strcmp(buffer, "CONNECTORS") == 0) { //load connector stuff s->nconnectors = n; _imd_load_connectors(&pFileData, s); } else if (strcmp(buffer, "ANIMOBJECT") == 0) { s->objanimtime = n; if (sscanf(pFileData, "%d %d%n", &s->objanimcycles, &s->objanimframes, &cnt) != 2) { debug(LOG_ERROR, "%s bad ANIMOBJ: %s", filename.toUtf8().constData(), pFileData); return nullptr; } pFileData += cnt; s->objanimdata.resize(s->objanimframes); for (int i = 0; i < s->objanimframes; i++) { int frame; Vector3i pos, rot; if (sscanf(pFileData, "%d %d %d %d %d %d %d %f %f %f%n", &frame, &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z, &s->objanimdata[i].scale.x, &s->objanimdata[i].scale.y, &s->objanimdata[i].scale.z, &cnt) != 10) { debug(LOG_ERROR, "%s: Invalid object animation level %d, line %d, frame %d", filename.toUtf8().constData(), level, i, frame); } ASSERT(frame == i, "%s: Invalid frame enumeration object animation (level %d) %d: %d", filename.toUtf8().constData(), level, i, frame); s->objanimdata[i].pos.x = pos.x / INT_SCALE; s->objanimdata[i].pos.y = pos.z / INT_SCALE; s->objanimdata[i].pos.z = pos.y / INT_SCALE; s->objanimdata[i].rot.pitch = -(rot.x * DEG_1 / INT_SCALE); s->objanimdata[i].rot.direction = -(rot.z * DEG_1 / INT_SCALE); s->objanimdata[i].rot.roll = -(rot.y * DEG_1 / INT_SCALE); pFileData += cnt; } } else { debug(LOG_ERROR, "(_load_level) unexpected directive %s %d", buffer, n); break; } } // FINALLY, massage the data into what can stream directly to OpenGL glGenBuffers(VBO_COUNT, s->buffers); vertexCount = 0; for (int k = 0; k < MAX(1, s->numFrames); k++) { // Go through all polygons for each frame for (unsigned i = 0; i < s->npolys; i++) { const iIMDPoly *pPolys = &s->polys[i]; // Do we already have the vertex data for this polygon? indices.append(addVertex(s, 0, pPolys, k)); indices.append(addVertex(s, 1, pPolys, k)); indices.append(addVertex(s, 2, pPolys, k)); } } glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_VERTEX]); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_NORMAL]); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(GLfloat), normals.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->buffers[VBO_INDEX]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_TEXCOORD]); glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(GLfloat), texcoords.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind indices.resize(0); vertices.resize(0); texcoords.resize(0); normals.resize(0); *ppFileData = pFileData; return s; }
// ppFileData is incremented to the end of the file on exit! static iIMDShape *iV_ProcessIMD(const char **ppFileData, const char *FileDataEnd) { const char *pFileName = GetLastResourceFilename(); // Last loaded filename const char *pFileData = *ppFileData; char buffer[PATH_MAX], texfile[PATH_MAX], normalfile[PATH_MAX], specfile[PATH_MAX]; int cnt, nlevels; iIMDShape *shape; UDWORD level; int32_t imd_version; uint32_t imd_flags; bool bTextured = false; GLuint shader = 0; memset(normalfile, 0, sizeof(normalfile)); memset(specfile, 0, sizeof(specfile)); if (sscanf(pFileData, "%255s %d%n", buffer, &imd_version, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad version: (%s)", pFileName, buffer); assert(false); return NULL; } pFileData += cnt; if (strcmp(PIE_NAME, buffer) != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s not an IMD file (%s %d)", pFileName, buffer, imd_version); return NULL; } //Now supporting version PIE_VER and PIE_FLOAT_VER files if (imd_version != PIE_VER && imd_version != PIE_FLOAT_VER) { debug(LOG_ERROR, "iV_ProcessIMD %s version %d not supported", pFileName, imd_version); return NULL; } // Read flag if (sscanf(pFileData, "%255s %x%n", buffer, &imd_flags, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad flags: %s", pFileName, buffer); return NULL; } pFileData += cnt; /* This can be either texture or levels */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s expecting TEXTURE or LEVELS: %s", pFileName, buffer); return NULL; } pFileData += cnt; // get texture page if specified if (strncmp(buffer, "TEXTURE", 7) == 0) { int i, pwidth, pheight; char ch, texType[PATH_MAX]; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { texfile[i] = ch; } texfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "iV_ProcessIMD %s texture info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s: only png textures supported", pFileName); return NULL; } sstrcat(texfile, ".png"); if (sscanf(pFileData, "%d %d%n", &pwidth, &pheight, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad texture size: %s", pFileName, buffer); return NULL; } pFileData += cnt; /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; bTextured = true; } if (strncmp(buffer, "NORMALMAP", 9) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { normalfile[i] = ch; } normalfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "iV_ProcessIMD %s normal map info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s: only png normal maps supported", pFileName); return NULL; } sstrcat(normalfile, ".png"); /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } if (strncmp(buffer, "SPECULARMAP", 11) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { specfile[i] = ch; } specfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "%s specular map info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "%s: only png specular maps supported", pFileName); return NULL; } sstrcat(specfile, ".png"); /* Try -again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } // DEPRECATED SHADERS DIRECTIVE! Has been moved into levels block now. Remove me later. if (strncmp(buffer, "SHADERS", 7) == 0) { char vertex[PATH_MAX], fragment[PATH_MAX]; /* the first parameter for "textures" is always ignored; which is why we ignore nlevels read in above */ pFileData++; if (sscanf(pFileData, "%255s %255s%n", vertex, fragment, &cnt) != 2) { debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; shader = pie_LoadShader(pFileName, vertex, fragment); /* Try -yet again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } if (strncmp(buffer, "LEVELS", 6) != 0) { debug(LOG_ERROR, "iV_ProcessIMD: expecting 'LEVELS' directive (%s)", buffer); return NULL; } /* Read first LEVEL directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &level, &cnt) != 2) { debug(LOG_ERROR, "(_load_level) file corrupt -J"); return NULL; } pFileData += cnt; if (strncmp(buffer, "LEVEL", 5) != 0) { debug(LOG_ERROR, "iV_ProcessIMD(2): expecting 'LEVEL' directive (%s)", buffer); return NULL; } shape = _imd_load_level(&pFileData, FileDataEnd, nlevels, imd_version); if (shape == NULL) { debug(LOG_ERROR, "iV_ProcessIMD %s unsuccessful", pFileName); return NULL; } // assign shader to all levels, if old deprecated SHADERS directive used. FIXME remove this later. for (iIMDShape *psShape = shape; shader && psShape != NULL; psShape = psShape->next) { shape->shaderProgram = shader; } // load texture page if specified if (bTextured) { int texpage = iV_GetTexture(texfile); int normalpage = iV_TEX_INVALID; int specpage = iV_TEX_INVALID; ASSERT_OR_RETURN(NULL, texpage >= 0, "%s could not load tex page %s", pFileName, texfile); if (normalfile[0] != '\0') { debug(LOG_TEXTURE, "Loading normal map %s for %s", normalfile, pFileName); normalpage = iV_GetTexture(normalfile); ASSERT_OR_RETURN(NULL, normalpage >= 0, "%s could not load tex page %s", pFileName, normalfile); } if (specfile[0] != '\0') { debug(LOG_TEXTURE, "Loading specular map %s for %s", specfile, pFileName); specpage = iV_GetTexture(specfile); ASSERT_OR_RETURN(NULL, specpage >= 0, "%s could not load tex page %s", pFileName, specfile); } // assign tex pages and flags to all levels for (iIMDShape *psShape = shape; psShape != NULL; psShape = psShape->next) { psShape->texpage = texpage; psShape->normalpage = normalpage; psShape->specularpage = specpage; psShape->flags = imd_flags; } // check if model should use team colour mask if (imd_flags & iV_IMD_TCMASK) { int texpage_mask; pie_MakeTexPageTCMaskName(texfile); sstrcat(texfile, ".png"); texpage_mask = iV_GetTexture(texfile); ASSERT_OR_RETURN(shape, texpage_mask >= 0, "%s could not load tcmask %s", pFileName, texfile); // Propagate settings through levels for (iIMDShape *psShape = shape; psShape != NULL; psShape = psShape->next) { psShape->tcmaskpage = texpage_mask; } } } *ppFileData = pFileData; return shape; }
/*! * Load shape levels recursively * \param ppFileData Pointer to the data (usualy read from a file) * \param FileDataEnd ??? * \param nlevels Number of levels to load * \return pointer to iFSDShape structure (or NULL on error) * \pre ppFileData loaded * \post s allocated */ static iIMDShape *_imd_load_level(const char **ppFileData, const char *FileDataEnd, int nlevels, int pieVersion) { const char *pFileName = GetLastResourceFilename(); // Last loaded filename const char *pFileData = *ppFileData; char buffer[PATH_MAX] = {'\0'}; int cnt = 0, n = 0, i; iIMDShape *s = NULL; float dummy; if (nlevels == 0) { return NULL; } i = sscanf(pFileData, "%255s %n", buffer, &cnt); ASSERT_OR_RETURN(NULL, i == 1, "Bad directive following LEVEL"); s = new iIMDShape; // Optionally load and ignore deprecated MATERIALS directive if (strcmp(buffer, "MATERIALS") == 0) { i = sscanf(pFileData, "%255s %f %f %f %f %f %f %f %f %f %f%n", buffer, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &cnt); ASSERT_OR_RETURN(NULL, i == 11, "Bad MATERIALS directive"); debug(LOG_WARNING, "MATERIALS directive no longer supported!"); pFileData += cnt; } else if (strcmp(buffer, "SHADERS") == 0) { char vertex[PATH_MAX], fragment[PATH_MAX]; if (sscanf(pFileData, "%255s %255s %255s%n", buffer, vertex, fragment, &cnt) != 3) { debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer); return NULL; } s->shaderProgram = pie_LoadShader(pFileName, vertex, fragment); pFileData += cnt; } if (sscanf(pFileData, "%255s %d%n", buffer, &s->npoints, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(2): file corrupt"); return NULL; } pFileData += cnt; // load points ASSERT_OR_RETURN(NULL, strcmp(buffer, "POINTS") == 0, "Expecting 'POINTS' directive, got: %s", buffer); _imd_load_points(&pFileData, s); if (sscanf(pFileData, "%255s %d%n", buffer, &s->npolys, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(3): file corrupt"); return NULL; } pFileData += cnt; ASSERT_OR_RETURN(NULL, strcmp(buffer, "POLYGONS") == 0, "Expecting 'POLYGONS' directive, got: %s", buffer); _imd_load_polys(&pFileData, s, pieVersion); // NOW load optional stuff while (!AtEndOfFile(pFileData, FileDataEnd)) // check for end of file (give or take white space) { // Scans in the line ... if we don't get 2 parameters then quit if (sscanf(pFileData, "%255s %d%n", buffer, &n, &cnt) != 2) { break; } pFileData += cnt; if (strcmp(buffer, "LEVEL") == 0) // check for next level { debug(LOG_3D, "imd[_load_level] = npoints %d, npolys %d", s->npoints, s->npolys); s->next = _imd_load_level(&pFileData, FileDataEnd, nlevels - 1, pieVersion); } else if (strcmp(buffer, "CONNECTORS") == 0) { //load connector stuff s->nconnectors = n; _imd_load_connectors(&pFileData, s); } else { debug(LOG_ERROR, "(_load_level) unexpected directive %s %d", buffer, n); break; } } // FINALLY, massage the data into what can stream directly to OpenGL glGenBuffers(VBO_COUNT, s->buffers); vertexCount = 0; for (int k = 0; k < MAX(1, s->numFrames); k++) { // Go through all polygons for each frame for (int i = 0; i < s->npolys; i++) { const iIMDPoly *pPolys = &s->polys[i]; // Do we already have the vertex data for this polygon? indices.append(addVertex(s, 0, pPolys, k)); indices.append(addVertex(s, 1, pPolys, k)); indices.append(addVertex(s, 2, pPolys, k)); } } glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_VERTEX]); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_NORMAL]); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(GLfloat), normals.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->buffers[VBO_INDEX]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_TEXCOORD]); glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(GLfloat), texcoords.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind indices.resize(0); vertices.resize(0); texcoords.resize(0); normals.resize(0); *ppFileData = pFileData; return s; }
// Run from screen.c on init. Do not change the order of loading here! First ones are enumerated. bool pie_LoadShaders() { pie_internal::SHADER_PROGRAM program; int result; // Load some basic shaders memset(&program, 0, sizeof(program)); pie_internal::shaderProgram.push_back(program); int shaderEnum = 0; // TCMask shader for map-placed models with advanced lighting debug(LOG_3D, "Loading shader: SHADER_COMPONENT"); result = pie_LoadShader("Component program", "shaders/tcmask.vert", "shaders/tcmask.frag", { "colour", "teamcolour", "stretch", "tcmask", "fogEnabled", "normalmap", "specularmap", "ecmEffect", "alphaTest", "graphicsCycle", "ModelViewMatrix", "ModelViewProjectionMatrix", "NormalMatrix", "lightPosition", "sceneColor", "ambient", "diffuse", "specular", "fogEnd", "fogStart", "fogColor" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_COMPONENT, "Failed to load component shader"); // TCMask shader for buttons with flat lighting debug(LOG_3D, "Loading shader: SHADER_BUTTON"); result = pie_LoadShader("Button program", "shaders/button.vert", "shaders/button.frag", { "colour", "teamcolour", "stretch", "tcmask", "fogEnabled", "normalmap", "specularmap", "ecmEffect", "alphaTest", "graphicsCycle", "ModelViewMatrix", "ModelViewProjectionMatrix", "NormalMatrix", "lightPosition", "sceneColor", "ambient", "diffuse", "specular", "fogEnd", "fogStart", "fogColor" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_BUTTON, "Failed to load button shader"); // Plain shader for no lighting debug(LOG_3D, "Loading shader: SHADER_NOLIGHT"); result = pie_LoadShader("Plain program", "shaders/nolight.vert", "shaders/nolight.frag", { "colour", "teamcolour", "stretch", "tcmask", "fogEnabled", "normalmap", "specularmap", "ecmEffect", "alphaTest", "graphicsCycle", "ModelViewMatrix", "ModelViewProjectionMatrix", "NormalMatrix", "lightPosition", "sceneColor", "ambient", "diffuse", "specular", "fogEnd", "fogStart", "fogColor" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_NOLIGHT, "Failed to load no-lighting shader"); debug(LOG_3D, "Loading shader: SHADER_TERRAIN"); result = pie_LoadShader("terrain program", "shaders/terrain_water.vert", "shaders/terrain.frag", { "ModelViewProjectionMatrix", "paramx1", "paramy1", "paramx2", "paramy2", "tex", "lightmap_tex", "textureMatrix1", "textureMatrix2", "fogEnabled", "fogEnd", "fogStart", "fogColor" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_TERRAIN, "Failed to load terrain shader"); debug(LOG_3D, "Loading shader: SHADER_TERRAIN_DEPTH"); result = pie_LoadShader("terrain_depth program", "shaders/terrain_water.vert", "shaders/terraindepth.frag", { "ModelViewProjectionMatrix", "paramx2", "paramy2", "lightmap_tex", "textureMatrix1", "textureMatrix2" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_TERRAIN_DEPTH, "Failed to load terrain_depth shader"); debug(LOG_3D, "Loading shader: SHADER_DECALS"); result = pie_LoadShader("decals program", "shaders/decals.vert", "shaders/decals.frag", { "ModelViewProjectionMatrix", "paramxlight", "paramylight", "tex", "lightmap_tex", "lightTextureMatrix", "fogEnabled", "fogEnd", "fogStart", "fogColor" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_DECALS, "Failed to load decals shader"); debug(LOG_3D, "Loading shader: SHADER_WATER"); result = pie_LoadShader("water program", "shaders/terrain_water.vert", "shaders/water.frag", { "ModelViewProjectionMatrix", "paramx1", "paramy1", "paramx2", "paramy2", "tex1", "tex2", "textureMatrix1", "textureMatrix2", "fogEnabled", "fogEnd", "fogStart" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_WATER, "Failed to load water shader"); // Rectangular shader debug(LOG_3D, "Loading shader: SHADER_RECT"); result = pie_LoadShader("Rect program", "shaders/rect.vert", "shaders/rect.frag", { "transformationMatrix", "color" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_RECT, "Failed to load rect shader"); // Textured rectangular shader debug(LOG_3D, "Loading shader: SHADER_TEXRECT"); result = pie_LoadShader("Textured rect program", "shaders/rect.vert", "shaders/texturedrect.frag", { "transformationMatrix", "tuv_offset", "tuv_scale", "color", "texture" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_TEXRECT, "Failed to load textured rect shader"); debug(LOG_3D, "Loading shader: SHADER_GFX_COLOUR"); result = pie_LoadShader("gfx_color program", "shaders/gfx.vert", "shaders/gfx.frag", { "posMatrix" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_GFX_COLOUR, "Failed to load textured gfx shader"); debug(LOG_3D, "Loading shader: SHADER_GFX_TEXT"); result = pie_LoadShader("gfx_text program", "shaders/gfx.vert", "shaders/texturedrect.frag", { "posMatrix", "color", "texture" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_GFX_TEXT, "Failed to load textured gfx shader"); debug(LOG_3D, "Loading shader: SHADER_GENERIC_COLOR"); result = pie_LoadShader("generic color program", "shaders/generic.vert", "shaders/rect.frag", { "ModelViewProjectionMatrix", "color" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_GENERIC_COLOR, "Failed to load generic color shader"); debug(LOG_3D, "Loading shader: SHADER_LINE"); result = pie_LoadShader("line program", "shaders/line.vert", "shaders/rect.frag", { "from", "to", "color", "ModelViewProjectionMatrix" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_LINE, "Failed to load line shader"); // Text shader debug(LOG_3D, "Loading shader: SHADER_TEXT"); result = pie_LoadShader("Text program", "shaders/rect.vert", "shaders/text.frag", { "transformationMatrix", "tuv_offset", "tuv_scale", "color", "texture" }); ASSERT_OR_RETURN(false, result && ++shaderEnum == SHADER_TEXT, "Failed to load text shader"); pie_internal::currentShaderMode = SHADER_NONE; GLbyte rect[] { 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1 }; glGenBuffers(1, &pie_internal::rectBuffer); glBindBuffer(GL_ARRAY_BUFFER, pie_internal::rectBuffer); glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLbyte), rect, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); return true; }