I'm trying to display simple white cube in OpenGL with SDL. I've setup my VBO and IBO like this:
GLfloat vertexData[] =
{
-0.5f, -0.5f, -0.5f, // bot, left, back
-0.5f, 0.5f, -0.5f, // top, left, back
-0.5f, -0.5f, 0.5f, // bot, left, front
-0.5f, 0.5f, 0.5f, // top, left, front
0.5f, -0.5f, -0.5f, // bot, right, back
0.5f, -0.5f, 0.5f, // bot, right, front
0.5f, 0.5f, -0.5f, // top, right, back
0.5f, 0.5f, 0.5f // top, right, front
};
GLint indexData[] =
{
//back
0, 1, 6,
0, 5, 6,
//left
0, 2, 3,
0, 1, 3,
//right
4, 5, 7,
4, 6, 7,
//bot
0, 4, 5,
0, 2, 5,
//top
1, 3, 7,
1, 6, 7,
//front
2, 3, 7,
2, 5, 7
};
However, it looks like this:
What am I doing wrong?
Edit:
My init functions
bool App::OpenGLInit()
{
programID = glCreateProgram();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
std::string vertexString = getShaderFromFile("src/shader.vert");
const GLchar * vertexShaderSource = vertexString.c_str();
glShaderSource(vertexShader, 1, (const GLchar **)&vertexShaderSource, NULL);
glCompileShader(vertexShader);
glAttachShader(programID, vertexShader);
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
//Get fragment source
std::string fragmentString = getShaderFromFile("src/shader.frag");
const GLchar* fragmentShaderSource = fragmentString.c_str();
//Set fragment source
glShaderSource( fragmentShader, 1, (const GLchar **)&fragmentShaderSource, NULL );
//Compile fragment source
glCompileShader( fragmentShader );
glAttachShader(programID, fragmentShader );
glLinkProgram(programID);
return true;
}
bool App::OnInit()
{
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
if((screen = SDL_CreateWindow("Color Wars", 100, 100, 1024, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)) == NULL) {
return false;
}
if ((gl_context = SDL_GL_CreateContext(screen)) == NULL)
{
return false;
}
if((renderer = SDL_CreateRenderer(screen, -1, 0)) == NULL)
{
return false;
}
if (SDL_GL_SetSwapInterval(1) < 0)
return false;
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
return false;
}
if (!OpenGLInit())
return false;
game_screen = new GameScreen();
game_screen->Init(programID);
return true;
}
my Render functions:
void App::OnRender()
{
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( programID );
game_screen->Render(renderer);
glUseProgram( NULL );
SDL_GL_SwapWindow(screen);
}
void GameScreen::Render(SDL_Renderer *renderer)
{
//Enable vertex position
glEnableVertexAttribArray(vertex2DPosition);
//Set vertex data
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glVertexAttribPointer(vertex2DPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL );
//Set index data and render
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IBO );
glDrawElements(GL_TRIANGLE_FAN, 12, GL_UNSIGNED_INT, NULL );
//Disable vertex position
glDisableVertexAttribArray( vertex2DPosition );
}
Dummy text: asdasdasdasdasdasd
You have three things working against you in this example:
You are drawing a cube in Normalized Device Coordinates, which have the range XYZ: [-1,1].
You are drawing into a window that is not square, so the cube face is stretched because your coordinate space has nothing to do with the size of your window.
It appears to be a rectangle because you have not defined any viewing transformation and are viewing it face-on with no perspective.
You can correct all of this if you do this whenever your window is resized:
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho ((-1.0f * aspect), (1.0f * aspect), -1.0f, 1.0f, -1.0f, 1.0f);
glViewport (0, 0, width, height);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glRotatef (45.0f, 0.25f, 0.5f, 0.75f); // Let's rotate this sucker!
Where width and height are the width and height of your SDL window, respectively.
UPDATE:
See, now it is clear why this did not work. You never mentioned in your question that you were using shaders. Thank you for posting your updated code. In order for this to work with shaders you need to pass a projection and modelview matrix. You can use the same setup to build your matrices as I described using the old OpenGL matrix manipulation functions, and glm would probably make this easiest.
Related
I used matrices from cglm to modify the camera and what I should've seen on the screen is a small square, but nothing shows up. I have this code:
#define GLEW_STATIC
#define STB_IMAGE_IMPLEMENTATION
#include<stdio.h>
#include<stdlib.h>
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<stdbool.h>
#include<string.h>
#include<stb/stb_image.h>
#include<cglm/cglm.h>
const unsigned int width = 1054;
const unsigned int height = 1057;
GLint uniColor;
GLint xploc;
GLint yploc;
void key_callback();
int main(){
if(!glfwInit()){
printf("Failed to initialize glfw!\n");
return 1;
}else{
printf("Successfully initialized glfw!\n");
}
//Set up GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(width, height, "Title", NULL, NULL);
glfwSetKeyCallback(window, key_callback);
if(!window){
printf("Window creation failed!\n");
return 1;
}else{
printf("Window created successfully!\n");
}
glfwMakeContextCurrent(window);
//Initialize GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
printf("Failed to initialize glew!\n");
return 1;
}else{
printf("Successfully initialized glew!\n");
}
//Set the swap interval to 1 millisecond
glfwSwapInterval(1);
//Set the vertices of the square
float Vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f
};
//Set indices to make the square work
GLuint indices[] = {
0, 2, 1,
0, 3, 2
};
//Ignore this - it was the original square, but then I realized how I actually needed to make it work
float VerticesSquare[] = {
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
printf("GLfloat variable called successfully\n");
//Create, compile and link the shaders to the shader program
GLuint ShaderProgram = glCreateProgram();
GLuint ShaderObjv = glCreateShader(GL_VERTEX_SHADER);
GLuint ShaderObjf = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* pvs[1];
const GLchar* pfs[1];
//Set the shader code
const char* pVertexShaderText = "#version 330 core\n"
"layout(location = 0) in vec3 Position;\n"
"layout(location = 1) in vec3 incolor;\n"
"layout(location = 2) in vec2 Tex;\n"
"out vec3 outcolor;\n"
"out vec2 texcoords;\n"
"uniform uint xp;\n"
"uniform uint yp;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 proj;\n"
"void main(){\n"
" gl_Position = proj * view * model * vec4(Position, 1.0f);\n"
"outcolor = incolor;\n"
"texcoords = Tex;\n"
"}";
const char* pFragmentShaderText = "#version 330 core\n"
"uniform vec3 color;\n"
"uniform sampler2D tex0;\n"
"in vec3 outcolor;\n"
"in vec2 texcoords;\n"
"out vec4 FragColor;\n"
"void main(){\n"
" FragColor = vec4(outcolor, 1.0f);\n"
"}";
pvs[0] = pVertexShaderText;
pfs[0] = pFragmentShaderText;
GLint LenghtsVertex[1];
GLint LenghtsFragment[1];
LenghtsVertex[0] = strlen(pVertexShaderText);
LenghtsFragment[0] = strlen(pFragmentShaderText);
glShaderSource(ShaderObjv, 1, pvs, LenghtsVertex);
glShaderSource(ShaderObjf, 1, pfs, LenghtsFragment);
glCompileShader(ShaderObjv);
glCompileShader(ShaderObjf);
//Shader error handling
GLint successvs;
glGetShaderiv(ShaderObjv, GL_COMPILE_STATUS, &successvs);
if(!successvs){
GLchar InfoLog1[1024];
glGetShaderInfoLog(ShaderObjv, sizeof(InfoLog1), NULL, InfoLog1);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog1);
return 1;
}
GLint successfs;
glGetShaderiv(ShaderObjf, GL_COMPILE_STATUS, &successfs);
if(!successfs){
GLchar InfoLog2[1024];
glGetShaderInfoLog(ShaderObjf, sizeof(InfoLog2), NULL, InfoLog2);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_FRAGMENT_SHADER, InfoLog2);
return 1;
}
glAttachShader(ShaderProgram, ShaderObjv);
glAttachShader(ShaderProgram, ShaderObjf);
glLinkProgram(ShaderProgram);
GLint success;
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success);
if(!success){
GLchar InfoLog3[1024];
glGetProgramInfoLog(ShaderProgram, sizeof(InfoLog3), NULL, InfoLog3);
fprintf(stderr, "Error linking shader program: '%s'\n", InfoLog3);
return 1;
}
glValidateProgram(ShaderProgram);
GLint successl;
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &successl);
if(!successl){
GLchar InfoLog4[1024];
glGetProgramInfoLog(ShaderProgram, sizeof(InfoLog4), NULL, InfoLog4);
fprintf(stderr, "Error validating shader program: '%s'\n", InfoLog4);
return 1;
}
glUseProgram(ShaderProgram);
//Set the vectors for the camera location
vec3 camerapos = {0.0f, 0.0f, -4.0f};
vec3 center = {0.0f, 0.0f, 0.0f};
vec3 yup = {0.0f, 1.0f, 0.0f};
//Create the matrices and make them be identity matrices
mat4 model;
mat4 view;
mat4 proj;
glm_mat4_identity(model);
glm_mat4_identity(view);
glm_mat4_identity(proj);
//Create the camera
glm_lookat(camerapos, center, yup, view);
glm_perspective(glm_rad(45.0f), (float)(width/height), 0.1f, 100.0f, proj);
//Set the uniform locations
GLint uniColor = glGetUniformLocation(ShaderProgram, "color");
GLint tex0uni = glGetUniformLocation(ShaderProgram, "tex0");
GLint xploc = glGetUniformLocation(ShaderProgram, "xp");
GLint yploc = glGetUniformLocation(ShaderProgram, "yp");
GLint modelloc = glGetUniformLocation(ShaderProgram, "model");
GLint viewloc = glGetUniformLocation(ShaderProgram, "view");
GLint projloc = glGetUniformLocation(ShaderProgram, "proj");
//Set the uniforms
glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);
glUniform1i(tex0uni, 0);
glUniform1ui(xploc, 1);
glUniform1ui(yploc, 1);
glUniformMatrix4fv(modelloc, 1, GL_FALSE, (float*)model);
glUniformMatrix4fv(viewloc, 1, GL_FALSE, (float*)view);
glUniformMatrix4fv(projloc, 1, GL_FALSE, (float*)proj);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//Create the buffers
GLuint VBO;
GLuint VAO = 0;
GLuint EBO;
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
printf("Buffer created successfully\n");
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
printf("Buffer data set up successfully\n");
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
printf("Enabling buffer successfull\n");
//Set the texture (I won't be using it for now)
int texwidth, texheight, texnum;
stbi_set_flip_vertically_on_load(true);
unsigned char* bytes = stbi_load("image.png", &texwidth, &texheight, &texnum, 0);
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float flatcolor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, flatcolor);
printf("Set parameters successfully\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, bytes);
glGenerateMipmap(GL_TEXTURE_2D);
printf("Texture set successfully\n");
//Set the VertexAttribPointers at locations 0, 1 and 2
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
printf("First pointer succeeded\n");
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
printf("Second pointer succeeded\n");
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
printf("Third pointer succeeded\n");
printf("Setting up VectexAttribPointer successfull\n");
while(!glfwWindowShouldClose(window)){
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//glDrawArrays(GL_TRIANGLES, 0, 3);
//Draw the elements
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
GLenum err;
if((err = glGetError()) != GL_NO_ERROR){
printf("OpenGL error: %d\n", err);
}
glfwSwapBuffers(window);
}
return 0;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_R && action == GLFW_PRESS){
glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);
}else if(key == GLFW_KEY_G && action == GLFW_PRESS){
glUniform3f(uniColor, 0.0f, 1.0f, 0.0f);
}else if(key == GLFW_KEY_B && action == GLFW_PRESS){
glUniform3f(uniColor, 0.0f, 0.0f, 1.0f);
}else if(key == GLFW_KEY_D && action == GLFW_PRESS){
glUniform1ui(xploc, 2);
}else if(key == GLFW_KEY_A && action == GLFW_PRESS){
glUniform1ui(xploc, 1);
}
}
I searched cglm's documentation, but didn't find a fix. There were some old stackoverflow questions on similar topics, but none actually solved my problem. I figured it has something to do with how I supply information to cglm's functions. I added comments, so it is easier to read.
As it turns out (float)(width/height) was supposed to be (float)width/(float)height as the first example was actually outputting 0 or 1, rather than 0.99716177861.
I’m trying to add freetype text to my running program. The code below was adapted from EdoardoLuciani. No text is shown, though.
I checked if the the tff file is loaded correctly and that valid textures ids are generated. They are o.k.
The remaining of the program is running without problem, but no text is drawn.
Could you help me to find what's wrong, please?
Environment:
DELL XPS
GPU 1050
OpenGL 4.6
Win32
Language C
// Main program
...
initText()
...
// Drawing loop
...
{
drawText(10, 300, "Hello World!");
}
void initText()
{
// Extract glyphs textures
//
glUseProgram(textShader);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, "arial.ttf", 0, &face);
FT_Set_Pixel_Sizes(face, 0, 48);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int c = 0; c < 128; c++)
{
FT_Load_Char(face, c, FT_LOAD_RENDER);
//
// Extract glyph
//
GLuint texture;
glCreateTextures(GL_TEXTURE_2D,1, &texture);
glTextureStorage2D(texture, 1, GL_R8, face->glyph->bitmap.width, face->glyph->bitmap.rows);
glTextureSubImage2D(texture, 0, 0, 0, face->glyph->bitmap.width, face->glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glBindTexture(GL_TEXTURE_2D, texture);
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);
glBindTexture(GL_TEXTURE_2D, 0);
//
// Save glyph to lookup table
//
Character ch;
ch.texture = texture;
ch.bearing[0] = face->glyph->bitmap.width;
ch.bearing[1] = face->glyph->bitmap.rows;
ch.size[0] = face->glyph->bitmap_left;
ch.size[1] = face->glyph->bitmap_top;
ch.advance = face->glyph->advance.x;
characters[c] = ch;
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
//
// Create VAO
//
glCreateVertexArrays(1, &textVAO);
glBindVertexArray(textVAO);
//
// Create the unique VBO
//
glCreateBuffers(1, &VBO);
glNamedBufferStorage(VBO, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayVertexBuffer(textVAO, 0, VBO, 0, sizeof(GLfloat) * 4);
glVertexArrayAttribFormat(textVAO, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(textVAO, 0, 0);
glEnableVertexArrayAttrib(textVAO, 0);
//
// Send color to fragment shader
//
glUniform3f(6, 0.88f, 0.59f, 0.07f);
}
void drawText(float x, float y, float scale, char *text)
{
glEnable(GL_CULL_FACE);
glUseProgram(textShader);
glBindVertexArray(textVAO);
//
// Draw each character
//
char *c = text;
while(*c != 0)
{
Character ch = characters[(int)*c];
if(ch.bearing[0] != 0 && ch.bearing[1] != 0)
{
GLfloat xpos = x + ch.bearing[0] * scale;
GLfloat ypos = y - (ch.size[1] - ch.bearing[1]) * scale;
//
GLfloat w = ch.size[0] * scale;
GLfloat h = ch.size[1] * scale;
//
// Update VBO for each character
//
GLfloat 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
};
glNamedBufferSubData(VBO, 0, sizeof(GLfloat)*6*4, vertices);
glBindTexture(GL_TEXTURE_2D, ch.texture);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
x += (ch.advance >> 6) * scale;
c++;
}
glDisable(GL_CULL_FACE);
}
The vertex shader:
#version 460 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
layout (location = 1) uniform mat4 projection;
out vec2 TexCoords;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}
The fragment shader:
#version 460 core
in vec2 TexCoords;
out vec4 color;
layout (binding = 0) uniform sampler2D text;
layout (location = 6) uniform vec3 textColor;
void main()
{
color = vec4(textColor, 1.0) * texture(text, TexCoords).r;
}
I am following the tutorials on learnopengl.com and I have come across an issues. I am writing my program in C rather than C++ and am using the linmath library for my matrix transformation and I have the files shader.c and texture.c. I believe that the issue is with my matrix transformation but I can't figure out where I've gone wrong. The program runs and it compiles, the window is created and the background colour is correct however the object does not show.
Here is the source:
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "linmath.h"
#include "shader.h"
#include "texture.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main(){
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL){
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD");
return -1;
}
Shader ourShader;
ourShader.ID = loadShader("3.3.shader.vs", "3.3.shader.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Texture tex1 = loadTexture("container.jpg");
Texture tex2 = loadTexture("awesomeface.png");
// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
useShader(ourShader.ID);
setIntShader("texture1", 0, ourShader.ID);
setIntShader("texture2", 1, ourShader.ID);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind textures on corresponding texture units
bindTexture(tex1, GL_TEXTURE0);
bindTexture(tex2, GL_TEXTURE1);
// activate shader
useShader(ourShader.ID);
// create transformations
mat4x4 model;
mat4x4 m;
mat4x4 view;
mat4x4 projection;
mat4x4_rotate(model, m, 1.0f, 0.0f, 0.0f, -0.95993f);
mat4x4_translate(view, 0.0f, 0.0f, -3.0f);
mat4x4_perspective(projection, 0.785f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// pass them to the shaders
setMat4Shader("model", model, ourShader.ID);
setMat4Shader("view", view, ourShader.ID);
setMat4Shader("projection", projection, ourShader.ID);
// render container
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
shader.c
#include "shader.h"
GLuint loadShader(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
char* VertexShaderCode;
FILE * vertexFile = fopen(vertex_file_path, "r");
if( vertexFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long vertex_file_size;
fseek(vertexFile, 0, SEEK_END);
vertex_file_size = ftell(vertexFile);
rewind(vertexFile);
VertexShaderCode = malloc((vertex_file_size + 1) * (sizeof(char)));
fread(VertexShaderCode, sizeof(char), vertex_file_size, vertexFile);
fclose(vertexFile);
VertexShaderCode[vertex_file_size] = 0;
// Read the Fragment Shader code from the file
char* FragmentShaderCode;
FILE * fragmentFile = fopen(fragment_file_path, "r");
if( fragmentFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long fragment_file_size;
fseek(fragmentFile, 0, SEEK_END);
fragment_file_size = ftell(fragmentFile);
rewind(fragmentFile);
FragmentShaderCode = malloc((fragment_file_size + 1) * (sizeof(char)));
fread(FragmentShaderCode, sizeof(char), fragment_file_size, fragmentFile);
fclose(fragmentFile);
FragmentShaderCode[fragment_file_size] = 0;
const char* vsCode = VertexShaderCode;
const char* fsCode = FragmentShaderCode;
// 2. compile shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vsCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fsCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
GLuint ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
return ID;
}
void useShader(unsigned int ID){
glUseProgram(ID);
}
void setBoolShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setIntShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setFloatShader(const char * name, float value, unsigned int ID)
{
glUniform1f(glGetUniformLocation(ID, name), value);
}
void setMat4Shader(const char * name, mat4x4 mat, unsigned int ID)
{
glUniformMatrix4fv(glGetUniformLocation(ID, name), 1, GL_FALSE, *mat);
}
void checkCompileErrors(GLuint shader, char type[])
{
GLint success;
GLchar infoLog[1024];
if(strncmp(type, "PROGRAM", 7) != 0)
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
}
texture.c
#include "texture.h"
Texture loadTexture(const char* path){
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load texture
int width, height, nrChannels;
unsigned char *data = SOIL_load_image(path, &width, &height, &nrChannels, SOIL_LOAD_RGB);
if(data){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else{
printf("Failed to load Image");
}
SOIL_free_image_data(data);
Texture t;
t.ID = texture;
t.path = path;
return t;
}
void bindTexture(Texture texture, GLenum unit){
// bind textures on corresponding texture units
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, texture.ID);
}
vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment Shader
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
// linearly interpolate between both textures (80% container, 20% awesomeface)
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
I am trying to use two separate shader programs for drawing two objects. When running the program only the object using the first shader program is rendered. Additionally, when deleting the first shader after it runs only the second object is rendered.
Code is below. Any help is appreciated.
void display()
{
mat4 mod, p, v;
glBindBuffer (GL_ARRAY_BUFFER, buffer);
//First Shader
glUseProgram(lightProgram);
p = perspective(zoom*45.0, aspect, zNear, zFar);
v = getViewMatrix();
mod = translate(0.0, 0.0, -5.0);
GLint objectColorLoc = glGetUniformLocation(lightProgram, "objectColor");
GLint lightColorLoc = glGetUniformLocation(lightProgram, "lightColor");
glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(lightColorLoc, 1.0f, 0.5f, 1.0f);
model = glGetUniformLocation( lightProgram, "model" );
view = glGetUniformLocation( lightProgram, "view" );
projection = glGetUniformLocation( lightProgram, "projection" );
glUniformMatrix4fv(projection, 1, GL_TRUE, &p.m[0][0]);
glUniformMatrix4fv( view, 1, GL_TRUE, &v.m[0][0] );
glBindVertexArray(containerVAO);
glUniformMatrix4fv( model, 1, GL_TRUE, &mod.m[0][0] );
glDrawArrays( GL_TRIANGLES, 0, 36 );
glBindVertexArray(0);
//glDeleteProgram(lightProgram);
//Model 2
//Second Shader
glUseProgram(lampProgram);
model = glGetUniformLocation( lampProgram, "model" );
view = glGetUniformLocation( lampProgram, "view" );
projection = glGetUniformLocation( lampProgram, "projection" );
glUniformMatrix4fv(projection, 1, GL_TRUE, &p.m[0][0]);
glUniformMatrix4fv( view, 1, GL_TRUE, &v.m[0][0] );
mod = translatevec3(lightPos);
glBindVertexArray (lightVAO);
glUniformMatrix4fv( model, 1, GL_TRUE, &mod.m[0][0] );
glDrawArrays( GL_TRIANGLES, 0, 36 );
glBindVertexArray(0);
}
Additionally I am creating my programs using
lightProgram = glCreateProgram();
glAttachShader(lightProgram, lightVertShader);
glAttachShader(lightProgram, lightFragShader);
glLinkProgram(lightProgram);
lampProgram = glCreateProgram();
glAttachShader(lampProgram, lampVertShader);
glAttachShader(lampProgram, lampFragShader);
glLinkProgram(lampProgram);
Thanks.
I hope to create an offScreen FBO, and use glReadPixels() to get the value of RGBA in this offScreen FBO. unfortunately, I got the error: GL_ERROR:0x0502
#import "ViewController.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#interface ViewController ()
{
GLuint backFBO;
GLuint defaultFBO;
int fbo_width;
int fbo_height;
//
GLuint _vertexArray;
GLuint _vertexBuffer;
GLuint _texCoordBuffer;
GLuint depthBuffer;
//
GLKMatrix4 _modelViewProjectionMatrix;
GLKMatrix3 _normalMatrix;
float _rotation;
}
#property (nonatomic, strong) GLKBaseEffect *baseEffect;
#property (nonatomic, strong) EAGLContext *context;
- (void)setupGL;
- (void)tearDownGL;
- (void)setupFBO;
#end
the vertex data and normal data of object in onScreen FBO
GLfloat gVertexData[] =
{
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f
};
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//1. setup context
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
];
if (!self.context) {
NSLog(#"Failed to create GLES Context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[self setupGL];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[self tearDownGL];
if ([EAGLContext currentContext] == self.context) {
[EAGLContext setCurrentContext:nil];
}
self.context = nil;
}
- (void) setupGL
{
[EAGLContext setCurrentContext:self.context];
self.baseEffect = [[GLKBaseEffect alloc] init];
glEnable(GL_DEPTH_TEST);
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gVertexData), gVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayOES(0);
// initialize FBO
[self setupFBO];
}
- (void) tearDownGL
{
[EAGLContext setCurrentContext:self.context];
glDeleteBuffers(1, &_vertexBuffer);
}
- (void)update
{
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
self.baseEffect.transform.projectionMatrix = projectionMatrix;
// Compute the model view matrix for the object rendered with ES2
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -2.0f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
self.baseEffect.transform.modelviewMatrix = modelViewMatrix;
_rotation += self.timeSinceLastUpdate * 0.5f;
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// render FBO tex
[self renderFBO];
// reset to main framebuffer
[((GLKView *) self.view) bindDrawable];
glViewport(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
// render main
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
#pragma mark - FBO
// intialize FBO
- (void)setupFBO
{
fbo_width = 512;
fbo_height = 512;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
NSLog(#"default FBO: %d", defaultFBO);
glGenFramebuffers(1, &backFBO);
glGenRenderbuffers(1, &depthBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbo_width, fbo_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
// FBO status check
GLenum status;
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
NSLog(#"fbo complete");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
NSLog(#"fbo unsupported");
break;
default:
/* programming error; will fail on all hardware */
NSLog(#"Framebuffer Error");
break;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
}
// render FBO
- (void)renderFBO
{
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
glViewport(0,0, fbo_width, fbo_height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
**//in here, I hope to get the value of RGBA in offScreen FBO**
Byte pixelColor[4] = {0,};
glReadPixels(50, 50, fbo_width, fbo_height, GL_RGBA, GL_UNSIGNED_BYTE, pixelColor);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
}
when I comment glReadPixels(), it's works well. Any help or advice would be much appreciated.
in your offScreen FBO, you should bind a GL_RENDERBUFFER, so you should add below code:
//create a new FBO
glBindFramebuffer(GL_FRAMEBUFFER, backFBO);
// add
GLuint _colorBuffer;
glGenRenderbuffers(1, &_colorBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, fbo_width , fbo_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER, _colorBuffer);
I hope this will fix your error. good luck !!!