Load multi texture opengl es 2.0 - c++

i'm found this piece of code on internet about how to load multi texture in opengl es 2.0:
//
// Book: OpenGL(R) ES 2.0 Programming Guide
// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10: 0321502795
// ISBN-13: 9780321502797
// Publisher: Addison-Wesley Professional
// URLs: http://safari.informit.com/9780321563835
// http://www.opengles-book.com
//
// MultiTexture.c
//
// This is an example that draws a quad with a basemap and
// lightmap to demonstrate multitexturing.
//
#include"pch.h"
#include <stdlib.h>
typedef struct
{
// Handle to a program object
GLuint programObject;
// Attribute locations
GLint positionLoc;
GLint texCoordLoc;
// Sampler locations
GLint baseMapLoc;
GLint lightMapLoc;
// Texture handle
GLuint baseMapTexId;
GLuint lightMapTexId;
} UserData;
///
// Load texture from disk
//
GLuint LoadTexture(char *fileName)
{
int width,
height;
char *buffer = esLoadTGA(fileName, &width, &height);
GLuint texId;
if (buffer == NULL)
{
esLogMessage("Error loading (%s) image.\n", fileName);
return 0;
}
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
free(buffer);
return texId;
}
///
// Initialize the shader and program object
//
int Init(ESContext *esContext)
{
UserData *userData = (UserData*) esContext->userData;
const char vShaderStr[] =
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
const char fShaderStr[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_baseMap; \n"
"uniform sampler2D s_lightMap; \n"
"void main() \n"
"{ \n"
" vec4 baseColor; \n"
" vec4 lightColor; \n"
" \n"
" baseColor = texture2D( s_baseMap, v_texCoord ); \n"
" lightColor = texture2D( s_lightMap, v_texCoord ); \n"
" gl_FragColor = baseColor * (lightColor + 0.25); \n"
"} \n";
// Load the shaders and get a linked program object
userData->programObject = esLoadProgram(vShaderStr, fShaderStr);
// Get the attribute locations
userData->positionLoc = glGetAttribLocation(userData->programObject, "a_position");
userData->texCoordLoc = glGetAttribLocation(userData->programObject, "a_texCoord");
// Get the sampler location
userData->baseMapLoc = glGetUniformLocation(userData->programObject, "s_baseMap");
userData->lightMapLoc = glGetUniformLocation(userData->programObject, "s_lightMap");
// Load the textures
userData->baseMapTexId = LoadTexture("basemap.tga");
userData->lightMapTexId = LoadTexture("lightmap.tga");
if (userData->baseMapTexId == 0 || userData->lightMapTexId == 0)
return FALSE;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return TRUE;
}
///
// Draw a triangle using the shader pair created in Init()
//
void Draw(ESContext *esContext)
{
UserData *userData = (UserData*)esContext->userData;
GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-0.5f, -0.5f, 0.0f, // Position 1
0.0f, 1.0f, // TexCoord 1
0.5f, -0.5f, 0.0f, // Position 2
1.0f, 1.0f, // TexCoord 2
0.5f, 0.5f, 0.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
// Set the viewport
glViewport(0, 0, esContext->width, esContext->height);
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(userData->programObject);
// Load the vertex position
glVertexAttribPointer(userData->positionLoc, 3, GL_FLOAT,
GL_FALSE, 5 * sizeof(GLfloat), vVertices);
// Load the texture coordinate
glVertexAttribPointer(userData->texCoordLoc, 2, GL_FLOAT,
GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
glEnableVertexAttribArray(userData->positionLoc);
glEnableVertexAttribArray(userData->texCoordLoc);
// Bind the base map
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId);
// Set the base map sampler to texture unit to 0
glUniform1i(userData->baseMapLoc, 0);
// Bind the light map
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, userData->lightMapTexId);
// Set the light map sampler to texture unit 1
glUniform1i(userData->lightMapLoc, 1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
///
// Cleanup
//
void ShutDown(ESContext *esContext)
{
UserData *userData = (UserData*)esContext->userData;
// Delete texture object
glDeleteTextures(1, &userData->baseMapTexId);
glDeleteTextures(1, &userData->lightMapTexId);
// Delete program object
glDeleteProgram(userData->programObject);
}
int main(int argc, char *argv[])
{
ESContext esContext;
UserData userData;
esInitContext(&esContext);
esContext.userData = &userData;
esCreateWindow(&esContext, L"MultiTexture", 320, 240, ES_WINDOW_RGB);
if (!Init(&esContext))
return 0;
esRegisterDrawFunc(&esContext, Draw);
esMainLoop(&esContext);
ShutDown(&esContext);
}
but when i run this it shows only dark! debugging the code shows that nothing is null or anything,so what's wrong with it?
i add two files named same as in the code but still i see a dark space!
any suggestion?
and another question is this is the common way to load any number of texture i want or not?

Try to draw a red square first (use gl_FragColor = vec4(1.0,0.0,0.0,1.0) ). If nothing draws, then change the order of your indices (you might have the normal backwards).
2nd , you need to commit the texture to the GPU before drawing.
You release the buffer before the GPU gets the chance of taking over the memory (you call free(buffer) before drawing anything with that texture, the buffer isn't on the GPU memory yet).
To commit a texture, draw something with that texture.
Here's a sample code of force commit (feel free to adapt it to your needs) :
void cColorTest::ForceCommitTexture(unsigned int texId)
{
glUseProgram(m_nProgram);
glBindTexture(GL_TEXTURE_2D,texId);
GLfloat triangle[]= { 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f};
glVertexAttribPointer ( m_nPosLoc, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), triangle );
glEnableVertexAttribArray ( m_nPosLoc );
glVertexAttribPointer ( m_nUVLoc, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), triangle + 4 );
glEnableVertexAttribArray ( m_nUVLoc );
glDrawArrays(GL_TRIANGLES,0,1);
}

Related

Texture isn't loading properly OpenGL

I am using MS visual studio 2019 and just learning opengl in c++. I started learning from https://learnopengl.com and it showed many ways to load textures . I just used stb image for loading textures and here's the function for loading a texture :
static unsigned int loadTexture(char const* path)
{
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char* data = stbi_load(path, &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
I tried loading it in a rectangle but somehow it doesn't seem to print properly on it. I'm stuck for a couple of hours and still couldn't find what mistake I've made.
here's the code for initializing the VAO and VBO:
inline void InitTextureBuffer(const char* img_filepath)
{
texture_shader.Bind();
tex_img_id = loadTexture(img_filepath);
glGenVertexArrays(1, &tex_VAO);
glGenBuffers(1, &tex_VBO);
glBindVertexArray(tex_VAO);
glBindBuffer(GL_ARRAY_BUFFER, tex_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
texture_shader.Unbind();
}
and function to draw the rect :
inline void Draw_Rectangle_IMG(_Point _min, _Point _max)
{
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(tex_VAO);
texture_shader.Bind();
float vertices[] =
{
_min.x, _min.y, 0.0f, 0.0f ,
_max.x, _min.y, 0.0f, 1.0f ,
_max.x, _max.y, 1.0f, 1.0f ,
_min.x, _min.y, 0.0f, 0.0f ,
_max.x, _max.y, 1.0f, 1.0f ,
_min.x, _max.y, 1.0f, 0.0f ,
};
glBindTexture(GL_TEXTURE_2D, tex_img_id);
glBindBuffer(GL_ARRAY_BUFFER, tex_VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
texture_shader.Unbind();
}
the shaders I've used:
const std::string texture_shader_vs =
{
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"layout(location = 1) in vec2 aTexCoord;\n"
"\n"
"out vec2 TexCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos,0.0f, 1.0f);\n"
" TexCoord = aTexCoord;\n"
"}\n"
};
const std::string texture_shader_fs =
{
"#version 330 core\n"
"out vec4 FragColor;\n"
"\n"
"in vec2 TexCoord;\n"
"\n"
"// texture sampler\n"
"uniform sampler2D texture1;\n"
"\n"
"void main()\n"
"{\n"
" FragColor = texture(texture1, TexCoord);\n"
"}\n"
};
And the function where I did the calls:
_Point p1, p2;
p1 = _Point(-0.5f, -0.25f);
p2 = _Point(0.5f, 0.25f);
ogl.InitTextureBuffer("resources/textures/1.png");
while (!glfwWindowShouldClose(ogl.GetWindow()))
{
glClear(GL_COLOR_BUFFER_BIT);
ogl.Draw_Rectangle_IMG(p1, p2);
glfwSwapBuffers(ogl.GetWindow());
glfwPollEvents();
}
The texture i tried to print is :
but the result I get is
I can't seem to find the error .Any help would be appreciated. Thanks!
The association of the texture coordinates to the vertices is wrong. Change to:
float vertices[] =
{
_min.x, _min.y, 0.0f, 1.0f,
_max.x, _min.y, 1.0f, 1.0f,
_max.x, _max.y, 1.0f, 0.0f,
_min.x, _min.y, 0.0f, 1.0f,
_max.x, _max.y, 1.0f, 0.0f,
_min.x, _max.y, 0.0f, 0.0f,
};
By default OpenGL assumes that the start of each row of an image is aligned to 4 bytes.
This is because the GL_UNPACK_ALIGNMENT parameter by default is 4. When a RGB image with 3 color channels is loaded to a texture object and 3*width is not divisible by 4 this may cause a misalignment.
Change the alignment by setting the GL_UNPACK_ALIGNMENT to 1, before specifying the texture image with glTexImage2D:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
When you remove glGenerateMipmap(GL_TEXTURE_2D);, then you have to change the minifying function (GL_TEXTURE_MIN_FILTER) as well. Since the filter is GL_LINEAR_MIPMAP_LINEAR, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST or GL_LINEAR.

Why is this texture not showing up?

I am following the tutorial from learnopengl.com to make a game engine.
I am using stb_image.h to load the textures, and my own header file to compile and link the shaders.
I got to the part in Getting Started/Textures where the container.jpg texture is supposed to fill up the rectangle on the window. But whenever I compile and run the code the texture does not appear anywhere in the window. This is my texture loading code:
// Load and create a texture
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// Set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load image, create texture, and generate minmaps
int width, height, nrChannels;
unsigned char* data = stbi_load("C:\\Users\\Lucas\\OneDrive\\Desktop\\C++ Projects\\Working Game Engine\\container.jpg", &width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture(s)\n";
}
These are the quad's coords:
float vertices[] = {
// Positions // Colors // Texture Coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
Render code:
// Process inputs
processInput(window);
// Render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Bind Texture
glBindTexture(GL_TEXTURE_2D, texture1);
// Render Container
ourShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Swap buffers and poll IO events (Key pressed/released, mouse moved etc.)
glfwSwapBuffers(window);
glfwPollEvents();
Vertex shader code:
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment shader code:
#version 460 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
Note that no error codes are returned from the image loader or shader compilers.
The rectangle appears like this.
You need to update the texture1 uniform like this:
glUniform1i(glGetUniformLocation(program_id, "texture1"), 0);
So it turns out I didn't glEnableVertexAttribArray(); the texture coords. Quite embarrassing.

OepnGL sampling multitpe textures returns same texture color

main.cpp
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <SOIL/SOIL.h>
typedef struct vertex{
float x; float y; float z;
float texX; float texY;
float texIndex;
} vertex;
void readTextFile(const char* path, std::string* dst);
int main(){
std::cout << 3 << std::endl;
GLFWwindow* window;
if(!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(640, 480, "Geometry Shader Bathing with Texture Atlas", NULL, NULL);
if(!window){
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGL();
glfwSwapInterval(1);
glFrontFace(GL_CW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//create and set vertex buffer
vertex vertices[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
};
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
//create vertex shader
std::string* shaderSource = new std::string();
readTextFile("shader/vertexShader.glsl", shaderSource);
const char* vertexShaderSourcePtr = shaderSource->c_str();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSourcePtr, NULL);
glCompileShader(vertexShader);
GLint status;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
char buffer[512];
glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
std::cout << "vertexShader FAIL : " << std::endl <<
shaderSource <<std::endl
<< buffer << std::endl;
}else{
std::cout << "vertexShader compile success!" << std::endl;
}
//create fragment shader
readTextFile("shader/fragmentShader.glsl", shaderSource);
const char* fragmentShaderSourcePtr = shaderSource->c_str();
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSourcePtr, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
char buffer[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
std::cout << "fragmentShader FAIL : " << std::endl <<
shaderSource <<std::endl
<< buffer << std::endl;
}else{
std::cout << "fragmentShader compile success!" << std::endl;
}
delete shaderSource;
//create and set program
GLint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "inPos");
glBindAttribLocation(program, 1, "inTex");
glBindAttribLocation(program, 2, "inTexIndex");
glLinkProgram(program);
//set frameBuffer(renderTarget) index and fragmentShader output name
glBindFragDataLocation(program, 0, "outColor");
glUseProgram(program);
//create and set texture
int width = 384;
int height = 384;
unsigned char* textureRawData0 = SOIL_load_image("resource/character/test0.png", &width, &height, 0, SOIL_LOAD_RGBA);
unsigned char* textureRawData1 = SOIL_load_image("resource/character/test1.png", &width, &height, 0, SOIL_LOAD_RGBA);
glUniform1i(glGetUniformLocation(program, "texture0"), 0);
glUniform1i(glGetUniformLocation(program, "texture1"), 1);
GLuint texture1;
glGenTextures(1, &texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData0);
SOIL_free_image_data(textureRawData0);
std:: cout << "texture0: " << glGetUniformLocation(program, "texture0") << std::endl;
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);
GLuint texture2;
glGenTextures(1, &texture2);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData1);
SOIL_free_image_data(textureRawData1);
std:: cout << "texture1: " << glGetUniformLocation(program, "texture1") << std::endl;
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);
//input layout : vertex Attribute
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glLinkProgram(program);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));
while(!glfwWindowShouldClose(window)){
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 12);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void readTextFile(const char* path, std::string* dst){
std::ifstream f;
f.open(path);
if(f.is_open()){
std::string buff;
dst->clear();
while(!f.eof()){
std::getline(f, buff);
dst->append(buff);
dst->push_back('\n');
}
dst->push_back('\0');
f.close();
}else{
std::cout << "파일 열기 실패 : " << *dst << std::endl;
}
}
ps
#version 330 core
in vec2 outTex;
in float outTexIndex;
out vec4 outColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main(){
if(outTexIndex == 0.0f){
outColor = texture(texture0, outTex);
}
else if(outTexIndex == 1.0f){
outColor = texture(texture1, outTex) + vec4(0.5f, 0.5f, 0.5f, 1.0f);
}
}
The input layout(vertex attribute) works fine.
TexIndex is transferred correctly. 1.0f and 0.0f
But the problem is
//fragment shader
texture(texture0, outTex);
texture(texture1, outTex);
both returns same texture color but it is actually different texture from test1.png and test2.png. what is the problem with my code?
++
I tried below fragment shader following the answer of #Rabbid76
#version 330 core
in vec2 outTex;
in float outTexIndex;
out vec4 outColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
vec4 c1 = texture(texture0, outTex) + vec4(0.5f, 0.0f, 0.0f, 1.0f);
vec4 c2 = texture(texture1, outTex) + vec4(0.0f, 0.5f, 0.0f, 1.0f);
outColor = mix(c1, c2, outTexIndex);
}
Color applied but still sampling from same the texture. looks like somehow glActiveTexture(i); doesn't work.
ps. test1.png and test2.png is completely different picture. above screenshot is test1.png
++ when I changed
glGenTexture(1, &texture0);
glGenTexture(1, &texture1);
to
glGenTexture(0, &texture0);
glGenTexture(0, &texture1);
then sampler2D texture0 and sampler2D texture1 both sample from texture1 test1.png (not form texture0 which is test0.png)
what is happening?
++
vs
#version 330
in vec3 inPos;
in vec2 inTex;
in float inTexIndex;
out vec2 outTex;
out float outTexIndex;
void main(){
outTex = inTex;
gl_position = vec4(inPos, 1.0f);
outTexIndex = inTexIndex;
}
Since the condition if(outTexIndex == 0.0f) depends on a fragment shader input, that may cause undefined behavior.
See (most recent) OpenGL Shading Language 4.60 Specification - 8.9. Texture Functions
[...] Some texture functions (non-“Lod” and non-“Grad” versions) may require implicit derivatives. Implicit derivatives are undefined within non-uniform control flow and for non-fragment shader texture fetches. [...]
respectively Non-uniform flow control.
Lookup both textures and mix the colors to solve the issue:
#version 330 core
in vec2 outTex;
in float outTexIndex;
out vec4 outColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
vec4 c1 = texture(texture0, outTex);
vec4 c2 = texture(texture1, outTex) + vec4(0.5f, 0.5f, 0.5f, 1.0f);
outColor = mix(c1, c2, outTexIndex);
}
I thought if I have a compiled example of multiple textures that working no problem, then I can find the problem of my code changing my code line to line comparing with the example. So I found this one.
tutorial
example code
It was SDL based. So I changed initialization code and loop to glfw. And It worked fine on my environment.
Even after I changed my code's texture loading part completely same with the example, the problem wasn't solved. So it must be other part that makes the problem. Finally, I found this.
//input layout : vertex Attribute
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//*****here!*****
//glLinkProgram(program);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));
After I just add two characters "//", result was shown as I intended.
I'm not sure about the reason that one line of code makes problem.

Switching more than one shader program (in OpenGL-ES 2.0)

I am really having nightmare to achieve what I required in OpenGles 2.0
Before posting the code reference, let me tell what I need.
I have 2D texture fragment shader. On top of the texture I want to draw red color line. I am able to draw the line but coloring to red is not working.
Shader declaration:
static const char s_v_shader[] =
"attribute vec4 vPosition; \n"
"attribute vec2 my_Texcoor; \n"
"uniform mat4 u_TransMatrix; \n"
"varying vec2 vTexcoor; \n"
"void main() \n"
"{ \n"
" vTexcoor = my_Texcoor; \n"
" gl_Position = u_TransMatrix*vPosition; \n"
"} \n";
static const char s_f_shader[] =
"precision mediump float;\n"
"uniform sampler2D my_Sampler; \n"
"varying vec2 vTexcoor; \n"
"void main() \n"
"{ \n"
" vec4 tex = texture2D(my_Sampler, vTexcoor); \n"
" gl_FragColor = tex; \n"
"} \n";
On top of texture I am rendering video frames from camera in infinite loop.
Before rendering video, I am setting up co-ordinates of 2D texture with below code.
Now I will explain my code from main function
main()
{
const GLfloat vertices[][2] = {
{ -1.0f, -1.0f},
{ 1.0f, -1.0f},
{ -1.0f, 1.0f},
{ 1.0f, 1.0f}
};
const GLfloat texcoords[][2] = {
{ 0.0f, 1.0f},
{ 1.0f, 1.0f},
{ 0.0f, 0.0f},
{ 1.0f, 0.0f}
};
GLfloat transformMatrix[16] =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
// setup OpenGl environment......
Setup_coordinates()
}
Setup_coordinates()
{
LoadShaders(s_v_shader, s_f_shader);
-- Complete function defined below
// By now I should be using shader program.
// Grab location of shader attributes.
GLint locVertices = glGetAttribLocation(programHandle, "vPosition");
GLint locTexcoord = glGetAttribLocation(programHandle, "my_Texcoor");
// Transform Matrix is uniform for all vertices here.
GLint locTransformMat = glGetUniformLocation(programHandle, "u_TransMatrix");
GLint locSampler = glGetUniformLocation(programHandle, "my_Sampler");
/* Create the texture. */
glGenTextures(1, &gTexObj);
glBindTexture(GL_TEXTURE_2D, gTexObj);
if (gTexObj == 0)
{
printf("Could not load the texture \n");
return -1;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniformMatrix4fv(locTransformMat, 1, GL_FALSE, transformMatrix);
glUniform1i(locSampler, 0);
glClearColor(0.0f, 0.5f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
while(1) -- Infinite loop to render video frames on 2D texture and draw red color line.
{
// enable vertex arrays to push the data.
glEnableVertexAttribArray(locVertices);
glEnableVertexAttribArray(locTexcoord);
// set data in the arrays.
glVertexAttribPointer(locVertices, 2, GL_FLOAT, GL_FALSE, 0, &vertices[0][0]);
glVertexAttribPointer(locTexcoord, 2, GL_FLOAT, GL_FALSE, 0, &texcoords[0][0]);
Render video frames logic goes here...................................
Each frame of video is abosultely rendering fine.
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Now comes the tricky part to draw the line and color it with red.
float red_left_1[] =
{
-0.85f, -0.9f, -0.6f, -0.5f,
};
glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, 0, red_left_1 );
glEnableVertexAttribArray (1 );
glDrawArrays ( GL_LINES , 0, 2 );
glLineWidth( width_test );
}
}
void LoadShaders(const char * vShader, const char * pShader)
{
vertShaderNum = glCreateShader(GL_VERTEX_SHADER);
pixelShaderNum = glCreateShader(GL_FRAGMENT_SHADER);
if (CompileShader(vShader, vertShaderNum) == 0)
{
printf("%d: PS compile failed.\n", __LINE__);
return;
}
if (CompileShader(pShader, pixelShaderNum) == 0)
{
printf("%d: VS compile failed.\n", __LINE__);
return;
}
programHandle = glCreateProgram();
glAttachShader(programHandle, vertShaderNum);
glAttachShader(programHandle, pixelShaderNum);
// Bind vPosition to attribute 0
glBindAttribLocation ( programHandle, 0, "vPosition" );
glLinkProgram(programHandle);
// Check if linking succeeded.
GLint linked = 0;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linked);
if (!linked)
{
printf("%d: Link failed.\n", __LINE__);
// Retrieve error buffer size.
GLint errorBufSize, errorLength;
glGetShaderiv(programHandle, GL_INFO_LOG_LENGTH, &errorBufSize);
char * infoLog = (char*)malloc(errorBufSize * sizeof (char) + 1);
if (infoLog)
{
// Retrieve error.
glGetProgramInfoLog(programHandle, errorBufSize, &errorLength, infoLog);
infoLog[errorBufSize + 1] = '\0';
fprintf(stderr, "%s", infoLog);
free(infoLog);
}
return;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glUseProgram(programHandle);
}
Most of the genius peoples suggested to declare one more shader as above but replace uniform sampler2D my_Sampler with uniform vec4 color.
void main()
{
gl_FragColor = color
}
Then switch between these shader programs while showing texture and drawing color lines using glUseProgram.
I tried and absolutely given up as switching to shader program for drawing lines is not working.
Here is code for generating a colored 1x1 texture that you can use for your line (goes in your main or Setup_coordinates). With this solution you won't need another shader.
GLuint lineTexture;
glGenTextures(1, &lineTexture);
unsigned char red[4] = { 255, 0, 0, 255};
glBindTexture(GL_TEXTURE_2D, lineTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, red);
glBindTexture(GL_TEXTURE_2D, 0);
Before calling glDrawArrays, use this to switch to the correct texture.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <lineTexture or gTexObj>);
glUniform1i(locSampler, 0);
A more general solution (that I personally implement in my OpenGL projects) is to create a white texture, add a color uniform to your shader and multiply the uniform with the texture2D return value. With this method you can create different colored lines and graphics from the same white texture, only changing the color uniform. For the video frames, you would send in a white color and the pixels will remain unchanged. This will require very few changes to your code, I'm sure you can figure it out if you think it sounds better. :)

SDL_TTF draws garbage

I asked a question the other day, about rendering TTF fonts using SDL, and was pointed towards SDL_TTFL I've tried using the SDL_TTF library, but All I'm getting is garbage on screen
I have included my shaders, which are very simple for this program, and also the snipped I'm using to load the text into surface, and to bind it to the texture. I'm not trying to do anything crazy here at all. Is there anything I'm doing wrong you can see? I'm not really too sure how to debug shaders etc.
Fragment Shader (frag.glsl):
#version 330
in vec2 texCoord;
in vec4 fragColor;
out vec3 finalColor;
uniform sampler2D myTextureSampler;
void main() {
finalColor = texture( myTextureSampler, texCoord ).rgb;
}
Vertex Shader (vert.glsl)
#version 330
in vec3 vert;
in vec4 color;
in vec2 texcoord;
out vec4 fragColor;
out vec2 texCoord;
void main() {
fragColor = color;
gl_Position = vec4(vert, 1);
texCoord = texcoord;
}
Font Loading (loadFont.cpp)
//Initialise TTF
if( TTF_Init() == -1 )
throw std::runtime_error("SDL_TTF failed to initialise.");
//Load the texture
font = TTF_OpenFont( filePath.c_str(), 12 );
if(!font)
throw std::runtime_error("Couldn't load: "+ filePath);
TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
surface = TTF_RenderUTF8_Blended(font, "Hello", this->textColor);
Uint8 colors = surface->format->BytesPerPixel;
int texture_format;
if (colors == 4) { // alpha
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
} else { // no alpha
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, colors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels);
SDL_FreeSurface(surface);
Vertex Attribute Setup
GLfloat vertices[] = {
//X Y Z R G B A U V
-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 1.f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 1.f,
-1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 0.f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 1.f,
1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 0.f,
-1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 0.f
};
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(program->attrib("vert"));
glVertexAttribPointer(program->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), NULL);
glEnableVertexAttribArray(program->attrib("color"));
glVertexAttribPointer(program->attrib("color"), 4, GL_FLOAT, GL_TRUE, 9*sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(program->attrib("texcoord"));
glVertexAttribPointer(program->attrib("texcoord"), 2, GL_FLOAT, GL_TRUE, 9*sizeof(GLfloat), (const GLvoid*)(7 * sizeof(GLfloat)));
I've attached the code I'm using for the vertex attributes as per the comment below.
EDIT:
In a reply that has been deleted since, It was asked whether SDL_TTF was returning 3 or 4 channels. It's returning a BGRA image. I've tried changing my fragment shader to
Fragment shader
#version 330
in vec2 texCoord;
in vec4 fragColor;
out vec4 finalColor;
uniform sampler2D myTextureSampler;
void main() {
finalColor = texture( myTextureSampler, texCoord ).rgba;
}
Note the vec4, and using rgba rather than rgb. This just leads to a black rectangle.
I also tried generating a surface using SDL_LoadBMP(), which gives the exact same results.
Your call to
glTexImage2D(GL_TEXTURE_2D, 0, colors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels);
Is a problem.
The third paramter is wrong:
http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml
internalFormat
Specifies the number of color components in the texture.
Must be one of base internal formats given in Table 1,
one of the sized internal formats given in Table 2, or one
of the compressed internal formats given in Table 3, below.
I suspect you want yours to be GL_RGBA (or what format you want opengl to store your texture in)
EDIT:
I just saw it now, but you are using only 3 channels in your fragment shader. The Blended function requires that you use 4 channels otherwise the alpha channel is going to be messed up.
I think your "main" problem lies somewhere else though as that should just make the colour constant over the entire surface. (Not the "garbage" you are seeing)
I quickly wrote this program that mostly does what your doing. I think it will help you more than my repository as it's straight to the point.
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_ttf.h>
#include <string>
#include <iostream>
using namespace std;
SDL_Window *window = NULL;
SDL_GLContext context = NULL;
TTF_Font* font = NULL;
SDL_Surface* surface = NULL;
//OpenGL Objects
GLuint vao;
GLuint vbo;
GLuint texture;
//Shader Objects
GLuint program;
GLuint vs;
GLuint fs;
//Sampler Object
GLuint uniformSampler;
//Callback Function
APIENTRY GLvoid debugMessageCallbackFunction( GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, GLvoid* userParam)
{
cerr << endl << "\t" << message << endl;
}
//The shaders are identical to yours
const string fragmentShaderString =
"#version 130\n" // My laptop can't do OpenGL 3.3 so 3.0 will have to do
"in vec2 texCoord;\n"
"in vec4 fragColor;\n"
"\n"
"out vec4 finalColor;\n"
"\n"
"uniform sampler2D myTextureSampler;\n"
"void main() {\n"
" finalColor = texture( myTextureSampler, texCoord ) * fragColor;\n"
"}";
const string vertexShaderString =
"#version 130\n"
"\n"
"in vec3 vert;\n"
"in vec4 color;\n"
"in vec2 texcoord;\n"
"\n"
"out vec4 fragColor;\n"
"out vec2 texCoord;\n"
"void main() {\n"
" fragColor = color;\n"
" gl_Position = vec4(vert, 1);\n"
" texCoord = texcoord;\n"
"}\n";
//Your vertices, but I changed alpha to 1.0f
const GLfloat vertices[] =
{
//X Y Z R G B A U V
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 1.f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 1.f,
-1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 0.f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 1.f,
1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 0.f,
-1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 0.f
};
int main(int argc, char* args[])
{
//Create Window and Context
window = SDL_CreateWindow("SDL Text with OpenGL", 0, 0, 640, 480, SDL_WINDOW_OPENGL);
//Set Core Context
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
context = SDL_GL_CreateContext(window);
//Simple OpenGL State Settings
glViewport( 0.f, 0.f, 640.f, 480.f);
glClearColor( 0.f, 0.f, 0.f, 1.f);
//Init Glew
//Set glewExperimental for Core Context
glewExperimental=true;
glewInit();
//Set Blending
//Required so that the alpha channels show up from the surface
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Simple callback function for GL errors
glDebugMessageCallbackARB(debugMessageCallbackFunction, NULL);
//Create Shaders
vs = glCreateShader(GL_VERTEX_SHADER);
fs = glCreateShader(GL_FRAGMENT_SHADER);
//Source Pointers
const GLchar* vsSource= &vertexShaderString[0];
const GLchar* fsSource = &fragmentShaderString[0];
//Set Source
glShaderSource(vs, 1, &vsSource, NULL);
glShaderSource(fs, 1, &fsSource, NULL);
//Compile Shaders
glCompileShader(fs);
glCompileShader(vs);
//Create Shader Program
program = glCreateProgram();
//Attach Shaders to Program
glAttachShader(program, vs);
glAttachShader(program, fs);
//No need for shaders anymore
glDeleteShader(vs);
glDeleteShader(fs);
//Set Attribute Locations
glBindAttribLocation(program, 0, "vert");
glBindAttribLocation(program, 1, "color");
glBindAttribLocation(program, 2, "texcoord");
//Link Program
glLinkProgram(program);
//Setup VAO and VBO
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 9 * 6, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), NULL);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),(GLvoid*)(3*sizeof(GLfloat)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),(GLvoid*)(7*sizeof(GLfloat)));
//Init TTF
TTF_Init();
//Open Font
font = TTF_OpenFont("DroidSansFallbackFull.ttf", 30);
SDL_Color color = {255, 255, 255, 255};
//Create Surface
surface = TTF_RenderUTF8_Blended(font, "This is TEXT!", color);
//Your format checker
GLenum format = (surface->format->BytesPerPixel==3)?GL_RGB:GL_RGBA;
//Create OpenGL Texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D( GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0,
format, GL_UNSIGNED_BYTE, surface->pixels);
//Set Some basic parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Set up Sampler
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
uniformSampler = glGetUniformLocation(program, "myTextureSampler");
//It defaults to using GL_TEXTURE0, so it's not necessary to set it
//in this program it's generally a good idea.
//--------------------------------------------------------------------------------------
// DRAW STAGE
//--------------------------------------------------------------------------------------
glUseProgram(program);
//glBindVertexArray(vao); - still in use
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
SDL_GL_SwapWindow(window);
//Sleep for 2s before closing
SDL_Delay(2000);
}
I didn't do any error checking or close any of the resources since it's just meant to be a reference and not meant to be used.
Usually I don't use glew, but writing code to manually get the functions for such a small program seemed pointless.
It compiles with
g++ source.cpp -g -lSDL2 -lSDL2_ttf -lGL -GLEW -o demo
on linux. You might need to make some adjustments for Windows (Headers files might change slightly and libraries will change as wel) and I think it will work without change on Mac.
EDIT 2:
To compile it on windows with mingw you need to add APIENTRY to callback function and the main should have arguments. Changed code to reflect this.
Tested it and it works on both windows and linux. (Provided that your implementation have access to the GL_ARB_debug_callback extension, if not just comment that out)
Does work nicely, only got to edit the const GLfloat vertices[] array to be able to change the text color consistently. For a solid color text, have all RGB components in the array equal to 1.0f and render the texture in color. For a multicolored text, first render the texture in white with SDL_Color color = { 255, 255, 255, 255 };, then edit the array as shown here below.
float width = (float)surface->w;
float height = (float)surface->h;
// alpha to 1.0f
const GLfloat vertices[] = {
// X Y Z R G B A U V
-1.0, -height / width, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, height / width, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.0f, -height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, height / width, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f
};