Same as above its single replacement routine but there should be header guard handling so you wont include the same file .
Theres a code with some cutouts
It uses std::string as CAnsiStting class and a vector of these as CStringList
#ifndef shaderclassH
#define shaderclassH
#include "/mnt/ext_sdcard/WNB/constvars.h"
//#include "windows_glext_fetcher.h"
#include "/mnt/ext_sdcard/WNB/txtfile/stringlist.cpp"
#include "/mnt/ext_sdcard/WNB/logme.cpp"
#include "/mnt/ext_sdcard/WNB/DxcMatrix.h"
//#include "/mnt/ext_sdcard/WNB/logme.cpp"
//#include <GLES/gl.h>
#include <GLES/gl.h>
#include <GLES3/gl3.h>
template <class T>
const T * readShaderFile( AnsiString FileName )
{
TStringList * s = new TStringList();
s->LoadFromFile(FileName);
AnsiString bollock = s->GetText();
//char* dest = new char[str.length() + 1];std::copy(str.begin(), str.end(), dest);
//now that would work
const T * buffer = new T[TextLength(bollock)];
buffer = bollock.c_str();
delete s;
return buffer;
}
struct TShaderObject
{
public:
// ~TShaderObject()
// {
//glDeleteProgram(gProgram);
// }
GLuint VERTEX;
GLuint FRAGMENT;
GLuint gProgram;
AnsiString Vertexdata;
AnsiString Fragmentdata;
GLint vertex_pos;
GLint texture_coord;
GLint vertex_normal;
GLint vertex_color;
void Enable()
{
glUseProgram(gProgram);
}
void Disable()
{
glUseProgram(0);
}
AnsiString LoadData(AnsiString fname, TStringList * cmd_list)
{
TStringList s;
s.LoadFromFile(fname);
//first apply dynamic consts
if (cmd_list != 0)
{
for (int i=0; i < cmd_list->Count; i++)
{
AnsiString var_name = get_before_char(cmd_list->Strings[i], ",", true );
AnsiString var_value = get_after_char(cmd_list->Strings[i], ",", true );
for (int n=0; n<s.Count;n++)
if (Pos(var_name, s.Strings[n]) > 0)
s.Strings[n] = StringReplace(s.Strings[n], var_name, var_value);
}
}
bool found = true;
// if (Pos("form", fname)>0) ALOG(s.GetText());
//parse file for #include directives and remove them
while (found)
for (int i=0; i<s.Count;i++)
{
found = false;
if (Pos("#include", s.Strings[i])>0)
{
TStringList p;
AnsiString fn = get_text_between("\"", "\"", s.Strings[i]);
ALOG("Including: "+fn);
if ( p.LoadFromFile(fn)== -1) ALOG("bad filename");
if (p.Count > 0)
{
s.Strings[i] = "";
int iline = i+1;
for (int l=0; l<p.Count;l++)
{
s.Strings.insert(s.Strings.begin()+iline, p.Strings[l]);
s.Count = s.Count+1;
iline = iline+1;
}
found = true;
break;
}
}
}
return s.GetText();
}
/*
template <class _t> bool LoadData(_t &data, const _t &filename)
{
std::ifstream file(filename.c_str(), std::ifstream::in | std::ifstream::ate);
if(file.is_open())
{
std::streampos size(file.tellg());
file.seekg(0, std::ios::beg);
data.reserve(size);
data.append((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
return true;
}
// ALOG("err in file");
return false;
}
*/
GLuint LoadShader(GLenum shaderType, const char* pSource)
{
GLuint shader = glCreateShader(shaderType);
ShowGLERROR();
if (shader)
{
glShaderSource(shader, 1, &pSource, NULL);
ShowGLERROR();
glCompileShader(shader);
GLint compiled = 0;
ShowGLERROR();
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
ShowGLERROR();
if (compiled == GL_FALSE)
{
GetShaderError(shader);
glDeleteShader(shader);
shader = 0;
}//!compiled
} //shader
return shader;
}
void GetShaderError(GLuint &shader)
{
int logSize = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
////alog("Error length: "+IntToStr(logSize));
std::vector<GLchar> error(logSize);
glGetShaderInfoLog(shader, logSize, &logSize, &error[0]);
if (logSize > 0)
{
AnsiString str = "";
int i;
for (i=0; i < logSize; i++)
str = str + error[i];
//str = "shader compile error: " + str;
ALOG(str);
}
//else //alog("bufflen 0 abroting - thers definetly an error during shader make");
}
void LoadVertexShader(AnsiString fname, TStringList * cmd_list)
{
ALOG("Loading vertex shader " + fname);
Vertexdata = "";
Vertexdata = LoadData(fname, cmd_list);
// LoadData(Vertexdata, fname);
VERTEX = LoadShader(GL_VERTEX_SHADER, Vertexdata.c_str());//readShaderFile<char>(fname));
// //alog("done");
}
void LoadFragmentShader(AnsiString fname, TStringList * cmd_list)
{
ALOG("Loading fragment shader " + fname);
Fragmentdata = "";
Fragmentdata = LoadData(fname, cmd_list);
// LoadData(Fragmentdata, fname);
FRAGMENT = LoadShader(GL_FRAGMENT_SHADER, Fragmentdata.c_str()); //readShaderFile<char>(fname));
// //alog("done");
}
void LoadVertexShaderStr(const char * source)
{
VERTEX = LoadShader(GL_VERTEX_SHADER, source);
}
void LoadFragmentShaderStr(const char * source)
{
FRAGMENT = LoadShader(GL_FRAGMENT_SHADER, source);
}
void LoadShaderProgramStr(const char * vs, const char * fs)
{
LoadVertexShaderStr(vs);
LoadFragmentShaderStr(fs);
}
void GetLinkerError()
{
GLint bufLength = 0;
glGetProgramiv(gProgram, GL_INFO_LOG_LENGTH, &bufLength);
//alog("Program error length: "+IntToStr(bufLength));
std::vector<GLchar> error(bufLength);
glGetProgramInfoLog(gProgram, bufLength, &bufLength, &error[0]);
if (bufLength > 0)
{
AnsiString str = "";
int i;
for (i=0; i < bufLength; i++)
str = str + error[i];
ALOG(str);
}
}
void createProgram()
{
gProgram = glCreateProgram();
if (gProgram) {
glAttachShader(gProgram, VERTEX);
glAttachShader(gProgram, FRAGMENT);
glLinkProgram(gProgram);
GLint linkStatus = GL_FALSE;
glGetProgramiv(gProgram, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_TRUE)
{
//alog("LINK STATUS: good");
vertex_pos = glGetAttribLocation(gProgram,"Vpos");
texture_coord = glGetAttribLocation(gProgram,"Vtexcoord");
vertex_normal = glGetAttribLocation(gProgram,"Vnormal");
vertex_color = glGetAttribLocation(gProgram,"Vcolor");
vertex_height = glGetAttribLocation(gProgram,"Vheight");
displacement = glGetAttribLocation(gProgram,"Vdisplacement");
////alog("DISPLACEMENT POS: "+IntToStr(displacement));
//
// MVP[0] = glGetUniformLocation(program, "MVP1");
// MVP[1] = glGetUniformLocation(program, "MVP2");
// MVP[2] = glGetUniformLocation(program, "MVP3");
// MVP[3] = glGetUniformLocation(program, "MVP4");
}
else {
//alog("LINK STATUS FALSE");
GetLinkerError();
glDeleteProgram(gProgram);
gProgram = 0;
}//linkstatus
}//program
}
bool initialized;
TShaderObject()
{
initialized = false;
}
~TShaderObject()
{
if (initialized)
glDeleteProgram(gProgram);
}
bool LoadShaderProgram(AnsiString vp, AnsiString fp, TStringList * cmd_list )
{
// ALOG(fp);
LoadVertexShader(vp, cmd_list);
// ShowGLERROR();
LoadFragmentShader(fp, cmd_list);
// ShowGLERROR();
createProgram();
// ShowGLERROR();
if (!gProgram) return false;
GetAllUniformLocations();
initialized = true;
return true;
}
bool LoadShaderProgram(AnsiString vp, AnsiString fp)
{
return LoadShaderProgram(vp, fp, 0);
}
bool LoadShaderStrProgram(const char * vp, const char * fp)
{
LoadVertexShaderStr(vp);
LoadFragmentShaderStr(fp);
createProgram();
if (!gProgram) return false;
GetAllUniformLocations();
initialized = true;
return true;
}
};
#endif
inline int Pos(AnsiString sub, AnsiString str)
{
std::size_t found = str.find(sub,0);
if (found!=AnsiString ::npos)
return int(found)+1;
else
return 0;
}
inline int pstrtoint(AnsiString num)
{
return ::atoi(num.c_str());
}
inline int StrToInt(AnsiString num)
{
return ::atoi(num.c_str());
}
inline AnsiString StringReplace(AnsiString str, AnsiString substr, AnsiString with)
{
AnsiString s = str;
while (Pos(substr, s) > 0)
{
int pos = Pos(substr, s)-1;
s.erase(pos,substr.length());
s.insert(pos, with);
}
return s;
}
struct TStringList
{
int Count;
std::vector<AnsiString> Strings;
void Delete(int line_index)
{
Strings.erase(Strings.begin() + line_index);
Count = Count - 1;
}
void Add(AnsiString text)
{
Strings.push_back(text);
Count = Count + 1;
}
void Add(TStringList * ins)
{
int ssize = ins->Count;
for (int i=0; i < ssize; i++)
Add(ins->Strings[i]);
}
AnsiString GetText()
{
AnsiString res = "";
int i;
for (i=0; i < Count; i++)
res = res + Strings[i] + "\n";
return res;
}
int GetSize()
{
AnsiString l = GetText();
return int ( l.length() ) * int ( sizeof ( unsigned char ) );
}
void Clear()
{
Count = 0;
Strings.clear();
}
TStringList()
{
Clear();
}
~TStringList()
{
Clear();
}
#define STRLST "WNB_LOG"
int LoadFromFile(AnsiString fname)
{
char delimiter ='\n';
std::ifstream in(fname.c_str());
if (in.good() == false) {
in.close();
return -1;
}
std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
if (Pos("\n", contents) > 0) delimiter = '\n';
if (Pos("\r", contents) > 0) delimiter = '\r';
//if (Pos("\n\r", contents) > 0) delimiter = '\n\r';
in.close();
std::ifstream file(fname.c_str());
if (file.good() == false) {
file.close();
//__android_log_print(ANDROID_LOG_VERBOSE, STRLST, "!Not good text file, aborting", 1+1);
return -1;
}
Clear();
AnsiString str;
// Count = 0;
// if (Strings.size() > 0) Strings.clear();
// __android_log_print(ANDROID_LOG_VERBOSE, STRLST, "!Loading file", 1+1);
while (std::getline(file, str, delimiter))
{
Strings.push_back(str);
// __android_log_print(ANDROID_LOG_VERBOSE, STRLST, str.c_str(), 1+1);
Count = Count + 1;
}
file.close();
//return 0;
for (int i=0; i < Count; i++)
{
AnsiString str = Strings[i];
if (str.length() == 0) continue;
char lastChar = str.at( str.length() - 1 );
if ( (lastChar == '\r') || (lastChar == '\n') )
{
str.erase(str.length()-1);
Strings[i] = str;
}
}
return 1;
}
//AnsiString p;
AnsiString pc;
void SaveToFile(AnsiString fname)
{
pc = GetText();
FILE* f = fopen(fname.c_str(),"w+");
int len = pc.length();
char * buff = new char[ len ];
memcpy(buff, pc.c_str(), sizeof ( char ) * len);
fwrite(&buff[0], sizeof ( char ) * len,1,f);
fclose(f);
/*
std::ofstream outfile (fname.c_str(),std::ofstream::binary);
int len = pc.length();
char * buff = new char[ len ];
memcpy(buff, pc.c_str(), sizeof(char) * len);
outfile.write (buff, len);
outfile.close();
*/
}
};