#include "HUD.h"
#include <vector>
#include <string>
extern const char* s_hudVertexShader;
extern const char* s_hudFragmentShader;
HUDRenderLayer::HUDRenderLayer()
{
}
HUDRenderLayer::~HUDRenderLayer()
{
}
/*
// concept, don't specify locations and uniform locations and vertex attribute layout
// instead define it more declaritively rather than programatically
// eg: list member variables that are uniforms, and the code is generated for this and inserted in to the shader code
// the attribute layout is also mapped from a struct and the members to map, and the code generated from sizeof struct and offsets
VariableMappings
{
consts, uniforms and attributes
attributes -> vertex shader
consts & uniforms -> both
}
*/
void HUDRenderLayer::initialize()
{
struct GLAttribute {
std::string m_type;
std::string m_name;
int m_count;
int m_glType;
int m_convert;
int m_size;
void* m_offset;
};
std::vector<GLAttribute> attributeList;
struct GLUniform {
std::string m_type;
std::string m_name;
int m_mappedLocation;
};
std::vector<GLUniform> uniformsList;
/*
struct {
int a[100], b[100], c[100];
} SOA;
struct {
int a, b, c;
} AOS[100];
*/
// Need to provide
struct thing {
float t;
float xyPos[2];//x,y;
float ch[2];//u,v;
float col[3];//r,g,b;
uint32_t col2;
} _thing;
// Need to provide
attributeList.emplace_back(GLAttribute{"float", "t", 1, GL_FLOAT, GL_FALSE, sizeof(_thing), (void*)((char*)&_thing.t - (char*)&_thing)});
attributeList.emplace_back(GLAttribute{"vec2", "xyPos", 2, GL_FLOAT, GL_FALSE, sizeof(_thing), (void*)((char*)&_thing.xyPos - (char*)&_thing)});
attributeList.emplace_back(GLAttribute{"vec2", "ch", 2, GL_FLOAT, GL_FALSE, sizeof(_thing), (void*)((char*)&_thing.ch - (char*)&_thing)});
attributeList.emplace_back(GLAttribute{"vec3", "col", 3, GL_FLOAT, GL_FALSE, sizeof(_thing), (void*)((char*)&_thing.col - (char*)&_thing)});
attributeList.emplace_back(GLAttribute{"vec4", "col2", 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(_thing), (void*)((char*)&_thing.col2 - (char*)&_thing)});
// uint32_t as color -> converts to a normalized vec4 in the shader
//glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 16+12, BUFFER_OFFSET(16));
// Example
//AddAttribute(col2);
// Perhaps look at the serialize/deserialize code I have
uniformsList.emplace_back(GLUniform{"highp vec2", "invScreen", 0});
uniformsList.emplace_back(GLUniform{"sampler2D", "texture", 1});
// Inject the attributes and uniforms in to the shaders
// Perhaps could inject in constants too
std::string vertexShaderDeclarations;
std::string fragmentShaderDeclarations;
for (auto attrib : attributeList)
vertexShaderDeclarations += "attribute " + attrib.m_type + " " + attrib.m_name + ";";
for (auto uniform : uniformsList)
{
vertexShaderDeclarations += "uniform " + uniform.m_type + " " + uniform.m_name + ";";
fragmentShaderDeclarations += "uniform " + uniform.m_type + " " + uniform.m_name + ";";
}
// Setup overlay vertexes
std::map<std::string,bool> options;
m_program.loadShaders((vertexShaderDeclarations + s_hudVertexShader).c_str(), (fragmentShaderDeclarations + s_hudFragmentShader).c_str(),
Medium, options,
[attributeList](GLuint a_program){
int idx = 0;
for (auto attrib : attributeList)
{
glBindAttribLocation(a_program, idx, attrib.m_name.c_str());
idx++;
}
}, [uniformsList](GLuint a_program){
int idx = 0;
for (auto uniform : uniformsList)
{
uniform.m_mappedLocation = glGetUniformLocation(a_program, uniform.m_name.c_str());
idx++;
}
});
GLuint vertexArray;
glGenVertexArraysOES(1, &vertexArray);
glBindVertexArrayOES(vertexArray);
glGenBuffers(1, &m_hudVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_hudVertexBuffer);
int idx = 0;
for (auto attrib : attributeList)
{
glVertexAttribPointer(idx, attrib.m_count, attrib.m_glType, attrib.m_convert, attrib.m_size, attrib.m_offset);
idx++;
}
glBindVertexArrayOES(0);
/*
//glBufferData (<#GLenum target#>, <#GLsizeiptr size#>, <#const GLvoid *data#>, <#GLenum usage#>);
//glBufferSubData(<#GLenum target#>, <#GLintptr offset#>, <#GLsizeiptr size#>, <#const GLvoid *data#>);
glGenTextures(1, &m_hudTexId);
glBindTexture(GL_TEXTURE_2D, m_hudTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
std::vector<unsigned char> fontData;
unsigned long fontW, fontH;
int error = ::decodePNG(fontData, fontW, fontH, Font6_png, Font6_png_len);
if (error != 0 || fontW != 256 || fontH != 256)
printf("error: %d\n", error);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid *)&fontData[0]);
*/
}
void HUDRenderLayer::update(float /*a_dt*/)
{
/*
m_hudItemCount = (int)m_chars.size();
const uint16_t fW = 10;
const uint16_t fH = 16;
m_items.clear();
for (TextChar c : m_chars)
{
uint8_t chX = 0, chY = 0;
if (c.ch == ' ')
{
m_hudItemCount--;
continue;
} else if (c.ch >= 'A' && c.ch <= 'Z') {
chX = (c.ch - 'A') * 10;
} else if (c.ch >= 'a' && c.ch <= 'z') {
chX = (c.ch - 'a') * 10;
chY = 16;
} else if (c.ch >= '0' && c.ch <= '9') {
chX = 1 + (c.ch - '0') * 10;
chY = 32;
} else {
if (c.ch == '.') {chX = 1; chY = 48;}
if (c.ch == '-') {chX = 11; chY = 48;}
if (c.ch == ',') {chX = 21; chY = 48;}
if (c.ch == '[') {chX = 31; chY = 48;}
if (c.ch == '_') {chX = 41; chY = 48;}
if (c.ch == ']') {chX = 51; chY = 48;}
if (c.ch == ':') {chX = 61; chY = 48;}
if (c.ch == '=') {chX = 71; chY = 48;}
if (c.ch == ';') {chX = 81; chY = 48;}
if (c.ch == '{') {chX = 91; chY = 48;}
if (c.ch == '+') {chX = 101; chY = 48;}
if (c.ch == '}') {chX = 111; chY = 48;}
if (c.ch == '@') {chX = 121; chY = 48;}
if (c.ch == '^') {chX = 131; chY = 48;}
if (c.ch == '#') {chX = 141; chY = 48;}
if (c.ch == '!') {chX = 151; chY = 48;}
if (c.ch == '*') {chX = 161; chY = 48;}
if (c.ch == '%') {chX = 171; chY = 48;}
// .----,
// [____]
//
// :====;
// {++++}
//
// @^^^^#
// !****%
//
// "╔═╗╚═╝"
//printf("Invalid char (%c)\n", c.ch);
}
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,0*fW,0*fH,c.col));
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,0*fW,1*fH,c.col));
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,1*fW,1*fH,c.col));
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,1*fW,1*fH,c.col));
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,1*fW,0*fH,c.col));
m_items.emplace_back(HudItem(c.x,c.y,chX,chY,0*fW,0*fH,c.col));
}
glBindBuffer(GL_ARRAY_BUFFER, m_hudVertexBuffer);
static_assert(sizeof(HudItem) == 16+12, "bad size");
glBufferData(GL_ARRAY_BUFFER, sizeof(HudItem)*m_hudItemCount*6, (void*)&m_items[0], GL_DYNAMIC_DRAW);
//m_chars.clear();
*/
}
void HUDRenderLayer::draw()
{
/*
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindVertexArrayOES(m_vertexArray[2]);
m_program.useProgram();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_hudTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glUniform1i(uniforms[UNIFORM_HUD_TEXTURE], 0);
//float invScreen[2] = { 2.0f / vp[2], -2.0f / vp[3] };
glUniform2f(uniforms[UNIFORM_HUD_INV_SCREEN], 2.0f / vp[2], -2.0f / vp[3]);
glDrawArrays(GL_TRIANGLES, 0, m_hudItemCount * 6);
*/
}