Main.cpp
//Variables
const unsigned int width = 896, height = 504;
//Initiating GLFW Window
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//Creating a GLFW window
window = glfwCreateWindow(width, height, "Jaguar", NULL, NULL);
//Checking if Window was initiated
if (window == NULL) {
std::cout << "GLFW FAILED TO INITIATE WINDOW!\n";
glfwTerminate();
}
glfwMakeContextCurrent(window);
//Centering Window
int windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, mode->width / 2 - windowWidth / 2, mode->height / 2 - windowHeight / 2);
//Setting-Up window's icon
GLFWimage icon[1];
icon[0].pixels = stbi_load("resources/images/gui/icon/icon.png", &icon[0].width, &icon[0].height, 0, 4);
glfwSetWindowIcon(window, 1, icon);
stbi_image_free(icon[0].pixels);
//Checking if Glad was initiated
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "GLAD FAILED TO BE INITIATED\n";
}
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
stbi_set_flip_vertically_on_load(true);
//Setting-Up Viewport
glViewport(0, 0, width, height);
//Intitiating MainMenu
states.push(new MainMenuState(*window, &states));
font.cpp
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
std::cout << "FREETYPE::Failed to initialize library\n";
}
FT_Face face;
if (FT_New_Face(ft, filePath, 0, &face)) {
std::cout << "FREETYPE::Failed to load to font: " << filePath << "\n";
}
// set size to load glyphs as
FT_Set_Pixel_Sizes(face, 0, px);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (unsigned char c = 0; c < 128; c++) {
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
std::cout << "FREETYPE::Failed to load glpyh\n";
}
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width,
face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top)
,face->glyph->advance.x };
Characters.insert(std::pair<char, Character>(c, character));
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
text.cpp
// activate corresponding render state
shader.use();
glUniform3f(glGetUniformLocation(shader.id, "textColor"), color.x, color.y,
color.z);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
// iterate through all characters
std::string::const_iterator c;
for (c = string.begin(); c != string.end(); c++)
{
Character ch = font.Characters[*c];
float xpos = position.x + ch.bearing.x * scale;
float ypos = position.y - (ch.size.y - ch.bearing.y) * scale;
float w = ch.size.x * scale;
float h = ch.size.y * scale;
// update VBO for each character
float vertices[6][4] = {
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos, ypos, 0.0f, 1.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
{ xpos + w, ypos + h, 1.0f, 0.0f }
};
// render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.textureId);
// update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// now advance cursors for next glyph (note that advance is number of
1/64 pixels)
position.x += (ch.advance >> 6) * scale; // bitshift by 6 to get value in
pixels (2^6 = 64)
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
Things I have already done:
Render text last
used gl_src_alpha, gl_one_minus_src_alpha
when i have depth testing disable it works just fine do I just enable and disable when needed??
if so how bad/good is it when it come to performance(game smoothness)
I have done some research on it and people are saying enable alpha blending do they mean gl_src_alpha, gl_one_minus_src_alpha
When you use Blending, you must disable the Depth Test. Enable the depth test when you draw the geometry, but disable the depth test before drawing the text. The depth test causes fragments to be discarded depending on the depth function. Blending takes the fragment color outputs from the Fragment Shader and combines them with the colors in the color buffers. Hence Blending is only applied to those fragments that are not discarded.
Related
I am working on a 2D game engine and I want to implement text rendering. I want to use freetype. I have the following code:
GLuint va;
glGenVertexArrays(1, &va);
GLuint vb;
glGenBuffers(1, &vb);
glBindVertexArray(va);
glBindBuffer(GL_ARRAY_BUFFER, vb);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
FT_Face testface;
FT_Error error;
error = FT_New_Face(ftlib, "arial.ttf", 0, &testface);
if (error == FT_Err_Unknown_File_Format)
{
std::cout << "Font format not supported" << std::endl;
}
else if (error)
{
std::cout << "Something else" << "\n";
}
error = FT_Set_Pixel_Sizes(testface, 0, 48);
if (error)
{
std::cout << "Problem with set px szes occ\n";
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (unsigned char c = 0; c < 128; c++)
{
if (FT_Load_Char(testface, c, FT_LOAD_RENDER))
{
std::cout << "Error. Failed to load glyph "<<c<<"\n";
continue;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
testface->glyph->bitmap.width,
testface->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
testface->glyph->bitmap.buffer
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Character newchar = {
texture,
glm::ivec2(testface->glyph->bitmap.width, testface->glyph->bitmap.rows),
glm::ivec2(testface->glyph->bitmap_left, testface->glyph->bitmap_top),
testface->glyph->advance.x
};
characters.insert(std::pair<char, Character>{c, newchar});
}
FT_Done_Face(testface);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glUseProgram(text_shader_program);
glUniform4f(glGetUniformLocation(text_shader_program, "textColor"), 1.f, 1.f, 1.f, 1.f);
glActiveTexture(GL_TEXTURE0);
std::string::const_iterator c;
std::string text = "TEST";
glBindVertexArray(va);
float x = 0.f;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = characters[*c];
float xpos = x + ch.bearing.x;
float ypos = 0.f - (ch.size.y - ch.bearing.y);
float w = ch.size.x;
float h = ch.size.y;
float vertices[6][4] = {
{xpos, ypos + h, 0.f, 0.f},
{xpos, ypos, 0.f, 1.f},
{xpos + w, ypos, 1.f, 1.f},
{xpos, ypos + h, 0.f, 0.f},
{xpos + w, ypos, 1.f, 1.f},
{xpos + w, ypos + h, 1.f, 0.f}
};
glBindTexture(GL_TEXTURE_2D, ch.textureID);
glBindBuffer(GL_ARRAY_BUFFER, vb);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.advance >> 6);
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
I initialize the library (before the above code happens) with
FT_Error error = FT_Init_FreeType(&ftlib);
if (error)
{
std::cout << "????" << std::endl;
}
The face and library initializes properly, glyphs are loaded, but nothing is drawn. I don't use camera, so all the coordinates are in space -1 to 1 if that matters.
I have the following shaders for text rendering:
vertexshader
#version 330 core
layout(location=0) in vec4 vertex;
out vec2 TextCoords;
void main() {
gl_Position = vec4(vertex.xy, 0.0, 1.0);
TextCoords = vertex.zw;
}
fragmentshader
#version 330 core
in vec3 TextCoords;
out vec4 color;
uniform sampler2D text;
uniform vec4 textColor;
void main(){
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TextCoords).r);
color = textColor * sampled;
}
Update:
I changed the line FT_Set_Pixel_Sizes(testface, 0, 48) to FT_Set_Pixel_Sizes(testface, 0, 1) and I got a huge gray rectangle where the text should be.
Has anyone got any ideas?
The problem seems to be the result of not using z-coordinate. The problem is, when using coordinate space -1 to 1, the text is rendering in too big scale to be seen or recognized. The solution is to use the z-coordinate as a static camera view, so for 500x500 window the borders are -250.f and 250.f
Working with OpenGL, GLM, GLAD, GLFW and FreeType attempting to get fonts to render. I've stepped through to make sure no OpenGL errors had occured while rendering, nothing posts an error code, but nothing renders to the screen. I'm also not sure if I'm using glm's ortho function correctly, because i'm not sure where to actually use the variable:
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
This is my Draw Loop, it gets called after the scene Initializes:
void GameLoop::Run()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
while (!glfwWindowShouldClose(m_game_window))
{
// Do That thing where you draw everything
}
}
The Font constructor which loads the font into textures:
Salem::Graphics::Font::Font(std::string p_font_path)
{
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
std::cout << "Error loading FreeType library" << std::endl;
}
FT_Face face;
if (FT_New_Face(ft, p_font_path.c_str(), 0, &face))
{
std::cout << "Error loading font;\n" << p_font_path << std::endl;
}
FT_Set_Pixel_Sizes(face, 0, 28);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Disable byte-alignment restriction
for (GLubyte c = 0; c < 128; c++)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
std::cout << "Failed to load a character glyph." << std::endl;
continue;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x
};
m_characters.insert(std::make_pair(c, character));
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
std::cout << "Font loaded. " << std::endl;
}
My text's Initialize function:
void Text::Initialize()
{
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vbo);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, nullptr, m_draw_method);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
And my text's draw function:
void Text::Draw()
{
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
shader()->Use();
glUniform3f(glGetUniformLocation(shader()->id(), "textColor"), m_color.x, m_color.y, m_color.z);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(m_vao);
for (std::string::const_iterator c = m_text.begin(); c != m_text.end(); ++c)
{
Character ch = m_font.characters()[*c];
GLfloat xPosition = m_position.x + ch.Bearing.x * m_scale;
GLfloat yPosition = m_position.y - (ch.Size.y - ch.Bearing.y) * m_scale;
GLfloat width = ch.Size.x * m_scale;
GLfloat height = ch.Size.y * m_scale;
GLfloat vertices[6][4] = {
{xPosition, yPosition + height, 0.0, 0.0},
{xPosition, yPosition, 0.0, 1.0},
{xPosition + width, yPosition, 1.0, 1.0},
{xPosition, yPosition + height, 0.0, 0.0},
{xPosition + width, yPosition, 1.0, 1.0},
{xPosition + width, yPosition + height, 1.0, 0.0}
};
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
m_position.x += (ch.Advance >> 6) * m_scale;
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
Didn't want the post to be too long, if my shaders are needed, let me know.
Upon breaking up the code, i found a helpful resource which lead me to my problem. From https://learnopengl.com/#!In-Practice/Text-Rendering Project source, I found that my orthographic projection variable had to be passed to my shader program when I was Constructing the font. I did this by add the following code to my Font Constructor:
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
p_shader->Use();
glUniformMatrix4fv(glGetUniformLocation(p_shader->id(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
I'm having trouble getting a TTF font to draw in OpenGL plus SDL2.0.
I remember that before SDL version 2 I had no problems, but there seems to be a lack of documentation on the subject, perhaps due to the new standard.
I have included the code below to show generally what I am doing.
This code is very inefficient as I recreate the Texture every frame, take this into consideration if copy+pasting :)
void main_render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Set our color back to white (Full texture color)
glColor3f(1.0f, 1.0f, 1.0f);
mainCamera->perspective();
mainCamera->translate();
//Load the font
TTF_Font *font = TTF_OpenFont("../resource/font.ttf", 10);
if (font == nullptr) {
std::cout << "TTF_OpenFont error: " << std::endl;
return;
}
//Render font to a SDL_Surface
SDL_Color color = {0,0,255,80};
SDL_Surface *surface = TTF_RenderText_Blended(font, "Hi!", color);
if (surface == nullptr) {
TTF_CloseFont(font);
std::cout << "TTF_RenderText error: " << std::endl;
return;
}
//Create a SDL_Texture * from the surface
SDL_Texture * text = SDL_CreateTextureFromSurface(fontRender, surface);
if (text == nullptr){
std::cout << "SDL_CreateTextureFromSurface error: " << std::endl;
return;
}
//Bind the SDL_Texture in OpenGL
SDL_GL_BindTexture(text, NULL, NULL);
//Draw the SDL_Texture * as a Quad
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS); {
glTexCoord2d(0, 0); glVertex3f(0, 0, 0);
glTexCoord2d(1, 0); glVertex3f(0 + surface->w, 0, 0);
glTexCoord2d(1, 1); glVertex3f(0 + surface->w, 0 + surface->h, 0);
glTexCoord2d(0, 1); glVertex3f(0, 0 + surface->h, 0);
} glEnd();
glDisable(GL_TEXTURE_2D);
//Cleanup
TTF_CloseFont(font);
SDL_DestroyTexture(text);
SDL_FreeSurface(surface);
//Swap the buffers to refresh the window
mainWindow->swap_buffers();
}
So OpenGL requires that all textures have dimensions of Base2 on my system (2,4,16,32,64...)
I fixed this problem by doing an incremental search for the closest power of two to the original dimension:
unsigned int power_two_floor(unsigned int val) {
unsigned int power = 2, nextVal = power*2;
while((nextVal *= 2) <= val)
power*=2;
return power*2;
}
I then ran into a snag: The texture was the correct color, yet the pixels were scrambled. This was fixed by copying the image to a RGB SDL_Surface, using the adjusted OpenGL dimensions.
//Find the first power of two for OpenGL image
int w = power_two_floor(surface->w)*2;
int h = power_two_floor(surface->h)*2;
//Create a surface to the correct size in RGB format, and copy the old image
SDL_Surface * s = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
SDL_BlitSurface(surface, NULL, s, NULL);
Adding filter information was required to correct OpenGL from utilizing mipmaps:
//Avoid mipmap filtering
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Here is my answer:
unsigned int power_two_floor(unsigned int val) {
unsigned int power = 2, nextVal = power*2;
while((nextVal *= 2) <= val)
power*=2;
return power*2;
}
void main_render() {
//Load the font
TTF_Font *font = TTF_OpenFont("../resource/font.ttf", 10);
if (font == nullptr) {
std::cout << "TTF_OpenFont error: " << std::endl;
return;
}
SDL_Color colorFg = {0,0,255};
SDL_Surface *surface;
//Render font to a SDL_Surface
if ((surface = TTF_RenderText_Blended(font, "Hi!", colorFg)) == nullptr) {
TTF_CloseFont(font);
std::cout << "TTF_RenderText error: " << std::endl;
return;
}
GLuint texId;
//Generate OpenGL texture
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
//Avoid mipmap filtering
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//Find the first power of two for OpenGL image
int w = power_two_floor(surface->w)*2;
int h = power_two_floor(surface->h)*2;
//Create a surface to the correct size in RGB format, and copy the old image
SDL_Surface * s = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
SDL_BlitSurface(surface, NULL, s, NULL);
//Copy the created image into OpenGL format
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
//Draw the OpenGL texture as a Quad
glBegin(GL_QUADS); {
glTexCoord2d(0, 1); glVertex3f(0, 0, 0);
glTexCoord2d(1, 1); glVertex3f(0 + surface->w, 0, 0);
glTexCoord2d(1, 0); glVertex3f(0 + surface->w, 0 + surface->h, 0);
glTexCoord2d(0, 0); glVertex3f(0, 0 + surface->h, 0);
} glEnd();
glDisable(GL_TEXTURE_2D);
//Cleanup
TTF_CloseFont(font);
SDL_FreeSurface(s);
SDL_FreeSurface(surface);
glDeleteTextures(1, &texId);
}
I started with opengl texturing and everything was working well. Now I am trying to load a bmp and make white part transparent using glEnable(GL_BLEND); and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
This is my source code:
float kSpeedForw=0.0f;
GLuint texture[1];
CCamera g_Camera;
GLfloat xrot = 0;
GLfloat yrot = 0;
GLfloat zrot = 0;
bool g_bFullScreen = true;
HWND g_hWnd;
RECT g_rRect;
HDC g_hDC;
HGLRC g_hRC;
HINSTANCE g_hInstance;
float jump = -0.1;
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
void Init(HWND hWnd)
{
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Position The Light
glEnable(GL_LIGHT1); // Enable Light One
glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
g_hWnd = hWnd;
GetClientRect(g_hWnd, &g_rRect);
InitializeOpenGL(g_rRect.right, g_rRect.bottom);
g_Camera.PositionCamera(0, 1.5f, 6, 0, 1.5f, 5, 0, 1, 0);
ShowCursor(false);
}
GLuint LoadTexture(const char * filename)
{
glEnable(GL_TEXTURE_2D);
GLuint texture;
int width, height;
unsigned char * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
if (filename=="Data/weed.bmp"){
width = 200;
height = 200;
}
if (filename == "Data/gun.bmp"){
width = 300;
height = 300;
}
data = (unsigned char *)malloc(width * height * 3);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
if (filename == "Data/weed.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
free(data);
}
if (filename == "Data/gun.bmp"){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3,width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
return texture;
}
WPARAM MainLoop() // main function
{
MSG msg;
Init(g_hWnd);
glClearColor(0, 0, 255, 0);
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if (LockFrameRate(60))
{
g_Camera.SetViewByMouse();
kSpeedForw = 0;
if (jump > -0.1)jump-=0.01;
CheckForMovement();
g_Camera.MoveCamera(kSpeedForw, jump);
RenderScene();
}
}
DeInit();
return(msg.wParam);
}
void RenderScene()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,
g_Camera.m_vView.x, g_Camera.m_vView.y, g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);
GLuint texture;
texture = LoadTexture("Data/weed.bmp");
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
float i = 0;
glColor3f(1,1,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, 10 - i / 5);
glTexCoord2f(50.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, -10 + i / 5);
glTexCoord2f(50.0f, 50.0f);
glVertex3f(10 - i / 5, 0, -10 + i / 5);
glTexCoord2f(0.0f, 50.0f);
glVertex3f(10 - i / 5, 0, 10 - i / 5);
glEnd();
////////////////////////////////////////////////////////////HUD
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SMOOTH);
glEnable(GL_BLEND); // Turn Blending On
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
GLuint ruka;
ruka = LoadTexture("Data/gun.bmp");
glBindTexture(GL_TEXTURE_2D, ruka);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(450,0);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(450,450);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0,450);
glEnd();
SwapBuffers(g_hDC);
}
The code works well for loading and rendering the platform(weed.bmp) and it also loads and renders gun fine. But big part of gun.bmp is white. I was hoping to get that part transparent. I was also hoping to add more HUD features, which would also need to be partly transparent.
My gun.bmp file: https://drive.google.com/file/d/0BxxlNcAI0eh9cHZGd1ZfMTFwYmM/view?usp=sharing
If you know a solution of this problem please post it. Thanks
You load image as GL_RGB, you want GL_RGBA to have an alpha channel.
Also, you need a 32 bits Bitmap (8 bits/channel × 4 channels = 32 bits).
I'm using SDL_ttf for rendering text with OpenGL. However, I'm getting nasty artifacts at edges of text:
Here's the code:
#include <string>
#include "SDL.h"
#include "SDL_opengl.h"
#include <SDL_ttf.h>
using namespace std;
#define WINDOW_WIDTH 1280
#define WINDOW_HEIGHT 1024
struct Color
{
unsigned char R, G, B, A;
Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) :
R(r), G(g), B(b), A(a)
{}
};
void DrawRectangle(int left, int right, int top, int bottom, Color c, GLuint Texture);
void DrawTextGL(int left, int top, TTF_Font* font, string text);
GLuint SDLSurfaceToTexture(SDL_Surface* surface);
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface* screen = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_OPENGL);
TTF_Init();
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, WINDOW_WIDTH, WINDOW_HEIGHT, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Enabling transparency
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
SDL_Surface* temp = SDL_LoadBMP("New Bitmap Image.bmp");
GLuint WhiteTexture = SDLSurfaceToTexture(temp);
TTF_Font* Font;
Font = TTF_OpenFont("FreeSerif.ttf", 36);
DrawRectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, Color(0, 0, 0, 255), WhiteTexture);
SDL_GL_SwapBuffers();
DrawTextGL(300, 300, Font, "graveyard");
DrawTextGL(600, 600, Font, "graveyard");
SDL_GL_SwapBuffers();
system("pause");
SDL_Quit();
return 0;
}
void DrawRectangle(int left, int right, int top, int bottom, Color c, GLuint Texture)
{
glBindTexture(GL_TEXTURE_2D, Texture);
glColor4f(c.R/255.0f, c.G/255.0f, c.B/255.0f, c.A/255.0f);
glBegin(GL_QUADS);
//Top-left vertex (corner)
glTexCoord2i(0, 0);
glVertex2f(GLfloat(left), GLfloat(top));
//Top-right vertex (corner)
glTexCoord2i(1, 0);
glVertex2f(GLfloat(right), GLfloat(top));
//Bottom-right vertex (corner)
glTexCoord2i(1, 1);
glVertex2f(GLfloat(right), GLfloat(bottom));
//Bottom-left vertex (corner)
glTexCoord2i(0, 1);
glVertex2f(GLfloat(left), GLfloat(bottom));
glEnd();
}
void DrawTextGL(int left, int top, TTF_Font* font, string text)
{
SDL_Color color = {255, 255, 255, 255};
SDL_Surface* textSurface;
textSurface = TTF_RenderText_Blended(font, text.c_str(), color);
GLuint Texture = SDLSurfaceToTexture(textSurface);
DrawRectangle(left, left + 260, top, top + 80, Color(255, 255, 255, 255), Texture);
SDL_FreeSurface(textSurface);
glDeleteTextures(1, &Texture);
}
GLuint SDLSurfaceToTexture(SDL_Surface* surface)
{
GLuint texture;
GLint nOfColors;
GLenum texture_format;
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
}
else if (nOfColors == 3)
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
}
else
{
printf("Picture with less than 24-bit color depth detected.\n");
return 0;
}
// Have OpenGL generate a texture object handle for us
glGenTextures(1, &texture);
// Bind the texture object
glBindTexture(GL_TEXTURE_2D, texture);
// Set the texture's stretching properties
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels);
// Bind the texture to which subsequent calls refer to
glBindTexture(GL_TEXTURE_2D, texture);
return texture;
}
"New Bitmap Image.bmp" is just a bitmap with one white pixel in it. "FreeSerif.ttf" is a font taken from here.