(progam) undeclared error - opengl

I have debugged this code to create a torus to the best of my ability and I still cannot get it to run. The errors I am getting are in my (void init()) specifically. It tells me that I have not declared vPosition and vNormal but I copy/pasted it directly from working code and I do not understand why it is not working. The code should produce a torus that is shaded and can be rotated using a mouse.
#include "mat.h"
#include "vec.h"
#include "Angel.h"
typedef Angel::vec4 color4;
typedef Angel::vec4 point4;
GLuint ModelView, Projection;
GLuint torus;
int click_button;
GLfloat click_rotation_x;
GLfloat click_rotation_y;
GLfloat click_position_z;
GLfloat click_x;
GLfloat click_y;
GLfloat rotation_x = 0.0;
GLfloat rotation_y = 0.0;
GLfloat position_z = -5;
GLuint buffers[1];
GLuint loc;
GLint matrix_loc, projection_loc, color_loc;
void mouse(int button, int state, int x, int y)
{
click_x = x;
click_y = y;
click_rotation_x = rotation_x;
click_rotation_y = rotation_y;
click_position_z = position_z;
}
void motion(int x, int y)
{
GLfloat dx = GLfloat(x - click_x) / 512;
GLfloat dy = GLfloat(y - click_y) / 512;
if (click_button == GLUT_MIDDLE_BUTTON)
{
rotation_x = click_rotation_x + 90.0 * dy;
rotation_y = click_rotation_y + 180.0 * dx;
if (rotation_x > 90.0) rotation_x = 90.0;
if (rotation_x < -90.0) rotation_x = -90.0;
if (rotation_y > 180.0) rotation_y -= 360.0;
if (rotation_y < -180.0) rotation_y += 360.0;
}
else
{
position_z = click_position_z + 5.0 * dy;
}
glutPostRedisplay();
}
struct vertex
{
vec3 v;
vec3 n;
};
const int n = 64;
const int m = 64;
struct vertex triangles[3*2*n*m];
struct vertex torus_vertex(float a, float b)
{
const float R = 2.0f;
const float r = 0.5f;
struct vertex vertex;
vertex.v.x = (R + r*cos(2.0*M_PI*a))* cos(2.0*M_PI*b);
vertex.v.y = (R + r*cos(2.0*M_PI*a))* sin(2.0*M_PI*b);
vertex.v.z = r*sin(2.0*M_PI*a);
vertex.n.x = cos(2.0*M_PI*a)* cos(2.0*M_PI*b);
vertex.n.y = cos(2.0*M_PI*a)* sin(2.0*M_PI*b);
vertex.n.z = sin(2.0*M_PI*a);
return vertex;
}
GLuint torus_create(GLuint vPosition, GLuint vNormal);
int i,j,k =0;
for (int i=0, i<n, i++)
for (int j=0, j<m, j++)
{
triangles[k++] = torus_vertex(float (i ) / n, float (j ) / n);
triangles[k++] = torus_vertex(float (i + 1) / n, float (j ) / n);
triangles[k++] = torus_vertex(float (i + 1) / n, float (j + 1) / n);
triangles[k++] = torus_vertex(float (i ) / n, float (j ) / n);
triangles[k++] = torus_vertex(float (i + 1) / n, float (j + 1) / n);
triangles[k++] = torus_vertex(float (i ) / n, float (j + 1) / n);
}
void
init()
{
GLuint (vbo);
glGenBuffers(1, &vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (struct vertex) * k, triangles, GL_STATIC_DRAW);
GLuint program = InitShader("vshader53.glsl", "fshader53.glsl");
glUseProgram( program );
glEnableVertexAttribArray(vPosition);
glEnableVertexAttribArray(vNormal);
glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, sizeof (struct vertex), (GLvoid *) 0);
glVertexAttribPointer(vNormal, 3, GL_FLOAT, GL_FALSE, sizeof (struct vertex), (GLvoid *) 12);
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
GLuint vNormal = glGetAttribLocation( program, "vNormal" );
glEnableVertexAttribArray( vNormal );
glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(vertex)) );
point4 light_position( 0.0, 0.0, -1.0, 0.0);
color4 light_ambient( 0.2, 0.2, 0.2, 1.0);
color4 light_diffuse( 1.0, 1.0, 1.0, 1.0);
color4 light_specular( 1.0, 1.0, 1.0, 1.0);
color4 material_ambient( 1.0, 0.0, 1.0, 1.0);
color4 material_diffuse( 1.0, 0.8, 0.0, 1.0);
color4 material_specular( 1.0, 0.8, 0.0, 1.0);
float material_shininess = 100.0;
color4 ambient_product = light_ambient * material_ambient;
color4 diffuse_product = light_diffuse * material_diffuse;
color4 specular_product = light_specular * material_specular;
glUniform4fv( glGetUniformLocation(program, "AmbientProduct" ), 1, ambient_product);
glUniform4fv( glGetUniformLocation(program, "DiffuseProduct" ), 1, diffuse_product);
glUniform4fv( glGetUniformLocation(program, "SpecularProduct"), 1, specular_product);
glUniform4fv( glGetUniformLocation(program, "LightPosition" ), 1, light_position);
glUniform1f( glGetUniformLocation(program, "Shininess"), material_shininess);
ModelView = glGetUniformLocation(program, "ModelView");
Projection = glGetUniformLocation(program, "Projection");
}
int
main()
{
printf("%d %d %d\n", n, m, k);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(512, 512);
glutCreateWindow("Torus");
glutMouseFunc(mouse);
glutMotionFunc(motion);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}

It looks like you are using the variables before you are defining them. Move the following from the middle of the init() function to the top of the init() function:
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
GLuint vNormal = glGetAttribLocation( program, "vNormal" );
glEnableVertexAttribArray( vNormal );
glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(vertex)) );

Related

C++ freetype add border to text with color and lenght

I've made an OpenGL c++ program that can display some text into the screen. I've followed
some tutorials and got help from this question. With that, I've managed to write a function called add_border but I didn't quite understand how this all works and couldn't manage to display border on the screen.
Here is what I have so far:
text.fs
#version 300 es
precision mediump float;
in vec2 vUV;
uniform sampler2D u_texture;
uniform vec3 textColor;
out vec4 fragColor;
void main()
{
vec2 uv = vUV.xy;
float text = texture(u_texture, uv).r;
fragColor = vec4(textColor.rgb*text, text);
}
text.vs
#version 300 es
precision mediump float;
layout (location = 0) in vec4 in_attr;
out vec2 vUV;
uniform mat4 projection;
uniform mat4 model;
void main()
{
vUV = in_attr.zw;
gl_Position = projection * model * vec4(in_attr.xy, 1.0f, 1.0f);
}
Text.cpp
void Text::render_text(std::string text, float x, float y, float z, std::string hex_color, float angle_rad, bool has_bg)
{
static const int scale = 1;
y /= 2;
shader.use();
glUniform3f(glGetUniformLocation(shader.ID, "textColor"), 0.9, 0.9, 0.9);
color.get_color_float(Utils::BLUE));
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
GLfloat vertices[6][4] = {
{ 0.0, 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 0.0, 1.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 0.0, 1.0, 0.0, 0.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 1.0, 1.0, 1.0, 0.0 }
};
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
glm::mat4 rotateM = glm::rotate(glm::mat4(1.0f), glm::radians(angle_rad), glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 transOriginM = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, z));
std::string::const_iterator c;
GLfloat char_x = 0.0f;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = Characters[*c];
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
GLfloat xrel = char_x + ch.Bearing.x * scale;
GLfloat yrel = y - (ch.Size.y - ch.Bearing.y) * scale;
char_x += (ch.Advance >> 6) * scale; )
glm::mat4 scaleM = glm::scale(glm::mat4(1.0f), glm::vec3(w, h, 1.0f));
glm::mat4 transRelM = glm::translate(glm::mat4(1.0f), glm::vec3(xrel, yrel, z));
glm::mat4 modelM = transOriginM * rotateM * transRelM * scaleM;
GLint model_loc = glGetUniformLocation(shader.ID, "model");
glUniformMatrix4fv(model_loc, 1, GL_FALSE, glm::value_ptr(modelM));
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Text::add_border(){
if(FT_Outline_New(ft_lib, 10000, 1000, &border) != 0){
VI_ERROR("Error");
}
FT_Stroker_New(ft_lib, &stroker);
FT_Stroker_Set(stroker, 2 * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
FT_Get_Glyph(face->glyph, &glyph);
FT_Glyph_Stroke(&glyph, stroker, false);
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
{
FT_Raster_Params params;
params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
//params.gray_spans = outlineRenderCallback;
//params.user = user_data;
FT_Outline_Render(ft_lib, &border, &params);
}
}
Text::Text(text_attributes&& atrib, int gl_width, int gl_height)
:SCR_WIDTH(gl_width), SCR_HEIGHT(gl_height)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader = Shader("./src/opengl/shaders/text.vs", "./src/opengl/shaders/text.fs");
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(SCR_WIDTH), 0.0f, static_cast<float>(SCR_HEIGHT));
shader.use();
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
if (FT_Init_FreeType(&ft_lib))
{
VI_ERROR("ERROR::FREETYPE: Could not init FreeType Library");
exit(0);
}
std::string font_name = "./src/opengl/fonts/" + *atrib.__font_name + ".ttf";
if (FT_New_Face(ft_lib, font_name.c_str(), 0, &face)) {
VI_ERROR("ERROR::FREETYPE: Failed to load font");
exit(0) ;
} else {
FT_Set_Pixel_Sizes(face, 0, atrib.__font_size);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (unsigned char c = 0; c < 128; c++)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
VI_ERROR("ERROR::FREETYTPE: Failed to load Glyph");
continue;
}
add_border();
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),
static_cast<unsigned int>(face->glyph->advance.x)
};
Characters.insert(std::pair<char, Character>(c, character));
}
glBindTexture(GL_TEXTURE_2D, 0);
}
FT_Done_Face(face);
FT_Outline_Done(ft_lib, &border);
FT_Done_FreeType(ft_lib);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
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);
}
I've read somewhere that changing FT_LOAD_RENDER to FT_LOAD_DEFAULT in FT_Load_Char() causes the text to disappear completely
Right now this code compiles and runs just fine, however there is no border around the text. I want to add some parameters to the add_border function to have it display different border's with the given parameters such as border thickness and border color.
What am I doing wrong? How can I have it display border like I want it to?
Based on the comments above:
The below example is based on my own lib (although very shortened), where i am collecting the coverage into an span array and render it later. It is also possible to render the coverage(s)/scanline directly onto a bitmap.
//structure to set the bounds
//and to hold a list of the coverage(s)
//basically the 'raw' data to produce a single glyph image
struct my_spans {
int x_min, y_min;
int x_max, y_max;
FT_Span *span_array; //needed later to reproduce the (glyph) image
};
struct my_spans spans; //initialize properly
//set the raster params accordingly
FT_Raster_Params params;
memset(&params, 0, sizeof(params));
params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; //direct rendering
params.gray_spans = outlineRenderCallback; //our callback below
params.user = &spans; //userdata will be our struct
//will be called for each scanline, thus the single y coordinate
void outlineRenderCallback(
int y,
int count,
const FT_Span *ft_spans,
void *user
){
struct my_spans *spans = (struct my_spans*) user;
FT_Span span;
//increase array capacity by count
//foreach span
for (int i=0; i < count; ++i, ++ft_spans) {
//horizontal boundary
spans->x_min = min(spans->x_min, ft_spans->x);
spans->x_max = max(spans->x_max, ft_spans->x + ft_spans->len - 1);
//span copy, although possible to write into array directly
span.x = ft_spans->x;
span.y = y;
span.len = ft_spans->len;
span.coverage = ft_spans->coverage;
//push span to array, if not written directly
}
//vertical boundary
spans->y_min = min(spans->y_min, y);
spans->y_max = max(spans->y_max, y);
}
Reference:
FT_Outline_Render
FT_Raster_Params
FT_SpanFunc
FT_Span

Drawing a plane with vertex buffer object

I'm trying to draw a square plane of 10 x 10 using the VBO on OpenGL. So I have a function getPlaneCoords that calculate the vertices and the indexes however the program just ends up crashing when I run it.
fragment shader:
#version 330 core
out vec4 color;
void main()
{
color = vec4(0.5, 0.2, 0.3, 1.0);
}
vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
FragPos = vec3(model * vec4(position, 1.0f));
}
Main.cpp:
constexpr GLuint dimensions{ 10 };
int numberOfPoints{ 0 };
int numberOfIndexes{ 0 };
float vertices[dimensions * dimensions * 3];
unsigned int indices[(dimensions - 1) * (dimensions - 1) * 6];
void getPlaneCoords()
{
int half = dimensions / 2;
for (int i{ 0 }; i < dimensions; ++i)
{
for (int j{ 0 }; j < dimensions; ++j)
{
float x = j - half;
float y = 0;
float z = i - half;
vertices[numberOfPoints++] = x;
vertices[numberOfPoints++] = y;
vertices[numberOfPoints++] = z;
}
}
for (int row{ 0 }; row < dimensions - 1; ++row)
{
for (int col{ 0 }; col < dimensions - 1; ++col)
{
indices[numberOfIndexes++] = dimensions * row + col;
indices[numberOfIndexes++] = dimensions * row + col + dimensions;
indices[numberOfIndexes++] = dimensions * row + col + dimensions + 1;
indices[numberOfIndexes++] = dimensions * row + col;
indices[numberOfIndexes++] = dimensions * row + col + dimensions + 1;
indices[numberOfIndexes++] = dimensions * row + col + 1;
}
}
}
int main()
{
glViewport(0, 0, WIDTH, HEIGHT);
// OpenGL options
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
getPlaneCoords();
// Build and compile our shader program
Shader lightingShader("lighting.vs", "lighting.frag");
GLuint squareVAO, VBO, EBO;
glGenVertexArrays(1, &squareVAO);
glBindVertexArray(squareVAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, numberOfPoints * sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfIndexes * sizeof(GLuint), indices, GL_STATIC_DRAW);
GLint PosAttrib{ glGetAttribLocation(lightingShader.Program, "position") };
glVertexAttribPointer(PosAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the normal vectors
glEnableVertexAttribArray(PosAttrib);
glBindVertexArray(0);
glm::mat4 projection = glm::perspective(camera.GetZoom(), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 1000.0f);
while(window.running)
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lightingShader.Use();
glm::mat4 view;
view = camera.GetViewMatrix();
// Get the uniform locations
GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");
GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");
// Pass the matrices to the shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(squareVAO);
glm::mat4 model = glm::mat4();
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, numberOfIndexes, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
window.display();
}
// Missing important display code but that is related to SFML. The code shared is primarily the OpenGL methods
}
It's meant to be a 10 x 10 plane with the color rgba ratio (0.5, 0.2, 0.3, 1.0);
I'm not sure as to where I went wrong?

SDL OpenGL Normal mapping

What is the simplest way of applying a normal map to a textured four vertex polygon in SDL? Do you have to create a shader or is there a simpler way? I have here my code that creates a textured rotating cube, with a rotating satellite light.
What additions to my code do I need to do if I want to use the generated texture (tex_Norm = generateTexture()) as a normal map also?
#include <windows.h>
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <math.h>
void initAll();
void setupBox();
void mainloop();
unsigned int generateTexture();
void handle_inputs();
void updateScreen();
void clean_up();
int scrWidth, scrHeight, flags;
bool bQuit = false;
float angle = 0.0f;
GLuint tex_Box, tex_Norm;
struct sVert
{
float x;
float y;
float z;
};
class cPolygon
{
public:
int v[4];
void fillverts(int v1, int v2, int v3, int v4) {
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
}
} p[6];
sVert pv[8];
int main(int argc, char *argv[])
{
initAll();
mainloop();
clean_up();
return 0;
}
void initAll()
{
scrWidth = 800;
scrHeight = 600;
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
flags = SDL_OPENGL | SDL_ANYFORMAT ;
SDL_SetVideoMode(scrWidth, scrHeight, 16, flags);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0f, (GLfloat)scrWidth/(GLfloat)scrHeight, 1.0f, 500.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
SDL_WM_SetCaption( "Normal Mapping", NULL );
tex_Box = generateTexture();
tex_Norm = generateTexture();
setupBox();
}
void setupBox()
{
for (int z=0;z<2;z++)
for (int y=0;y<2;y++)
for (int x=0;x<2;x++)
{
pv[x+y*2+z*4].x = -1.0+x;
pv[x+y*2+z*4].y = -1.0+y;
pv[x+y*2+z*4].z = -1.0+z;
}
// Box object
p[0].fillverts (0, 1, 3, 2); // above
p[1].fillverts (4, 5, 1, 0); // behind
p[2].fillverts (6, 7, 3, 2); // in front
p[3].fillverts (5, 7, 3, 1); // right
p[4].fillverts (0, 2, 6, 4); // left
p[5].fillverts (7, 6, 4, 5); // below
}
unsigned int generateTexture()
{
BYTE data[128*128*3];
unsigned int id;
for (int x=0;x<128;x++)
for (int y=0;y<128;y++)
{
data[y*128*3+x*3+0] = x; // Red
data[y*128*3+x*3+1] = y; // Green
data[y*128*3+x*3+2] = 128-(abs(64-x)+abs(64-y)); // Blue
}
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return id;
}
void mainloop()
{
while(bQuit == false)
{
handle_inputs();
updateScreen();
angle += 1.5f;
Sleep(50);
}
}
void handle_inputs()
{
SDL_PumpEvents();
Uint8 * keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_ESCAPE]) bQuit = true;
}
void updateScreen()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.0f, 0.0f, -3.0f);
glRotatef(-angle*2.0, 1.0f, 1.0f, 1.0f);
// Setup a light source
float lpos[] = {0.0, 0.0, 2.0, 1.0}; // position
float ldif[] = {1.0, 1.0, 1.0, 1.0}; // diffuse
float lamb[] = {0.3, 0.3, 0.2, 1.0}; // ambient
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glLightfv(GL_LIGHT0, GL_DIFFUSE, ldif);
glLightfv(GL_LIGHT0, GL_AMBIENT, lamb);
glPopMatrix();
glPushMatrix();
glTranslatef(0.5f, 0.5f, -3.0f);
glRotatef(angle, 1.0f, 1.0f, 1.0f);
// Draw box object
glBindTexture(GL_TEXTURE_2D, tex_Box);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
for(int pi=0; pi<6; pi++)
for(int vi=0; vi<4; vi++)
{
switch(vi) {
case 0: glTexCoord2d(0.0,2.0); break;
case 1: glTexCoord2d(0.0,0.0); break;
case 2: glTexCoord2d(2.0,0.0); break;
case 3: glTexCoord2d(2.0,2.0); break; };
glVertex3f( pv[ p[pi].v[vi] ].x,
pv[ p[pi].v[vi] ].y,
pv[ p[pi].v[vi] ].z );
};
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glFinish();
SDL_GL_SwapBuffers();
}
void clean_up()
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
glDeleteTextures(1, &tex_Box);
glDeleteTextures(1, &tex_Norm);
SDL_Quit();
}
Sorry, but if you want to use modern OpenGL features, you need modern OpenGL, which means shaders. :( That also means all your lighting needs to be done manually in the shader, so your program is going to get quite a bit more complicated, but that's the price you pay for cool images.
Explaining in detail how to do normal mapping wouldn't fit here, but there are very nice tutorials out there, for example http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/.
Good luck!
After some hours adventure into the world of GLSL and some help from the answer in this question: SDL OpenGL in C++, Texture Shader missing the texture
... I finally made a Normal map out of my generated texture. Here is the result:
#include <windows.h>
#include <SDL.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <string>
using namespace std;
#define LOG_SIZE 10000
void initAll();
void setupBox();
void mainloop();
unsigned int generateTexture();
void handle_inputs();
void updateScreen();
void clean_up();
void dbpf(int, const char *, ...);
int scrWidth, scrHeight, flags;
bool bQuit = false;
float angle = 0.0f;
va_list m;
int db_threashold = 0;
GLint status;
GLchar elog[LOG_SIZE];
GLint rLength = 0;
GLuint tex_Box, tex_Norm;
std::string vertex_source, fragment_source;
GLuint shader_program, vertex_shader, fragment_shader;
GLuint vao, vbo;
const char *source;
int length;
struct sVert
{
float x;
float y;
float z;
};
class cPolygon
{
public:
int v[4];
void fillverts(int v1, int v2, int v3, int v4) {
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
}
} p[6];
sVert pv[8];
int main(int argc, char *argv[])
{
initAll();
mainloop();
clean_up();
return 0;
}
void initAll()
{
scrWidth = 800;
scrHeight = 600;
vertex_source =
"#version 330\n"
"in vec3 Position;\n"
"in vec2 TexCoord;\n"
"out vec3 oColor;\n"
"out vec2 oTexcoord;\n"
"void main() {\n"
" oTexcoord = TexCoord;\n"
" gl_Position = gl_ModelViewProjectionMatrix*vec4(Position, 1.0);\n"
"}\n";
fragment_source =
"#version 330\n"
"in vec2 oTexcoord;\n"
"out vec4 oColor;\n"
"uniform sampler2D tex;\n"
"uniform sampler2D tex_norm;\n"
"void main() {\n"
" vec4 lightpos = normalize(-gl_ModelViewProjectionMatrix*vec4(1.0, -1.0, -1.5, 1.0));\n"
" vec3 tmpNorm = normalize(texture2D(tex_norm, oTexcoord).rgb * 2.0 - 1.0);\n"
" float difuse = max(dot(tmpNorm, lightpos.xyz), 0.0);\n"
" vec3 tmpcolor = difuse * texture2D(tex, oTexcoord).rgb;\n"
" oColor = vec4(tmpcolor, 1.0);\n"
"}\n";
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
flags = SDL_OPENGL | SDL_ANYFORMAT ;
SDL_SetVideoMode(scrWidth, scrHeight, 16, flags);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0f, (GLfloat)scrWidth/(GLfloat)scrHeight, 1.0f, 500.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
SDL_WM_SetCaption( "Normal map", NULL );
glewInit();
// vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
source = vertex_source.c_str();
length = vertex_source.size();
glShaderSource(vertex_shader, 1, &source, &length);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vertex_shader, LOG_SIZE, &rLength, elog);
dbpf(10, "Compile vertex log: \n %s \n", elog);
// fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
source = fragment_source.c_str();
length = fragment_source.size();
glShaderSource(fragment_shader, 1, &source, &length);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fragment_shader, LOG_SIZE, &rLength, elog);
dbpf(10, "Compile fragment log: \n %s \n", elog);
// create program
shader_program = glCreateProgram();
// attach shaders
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
// link the program and check for errors
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &status);
glGetProgramInfoLog(shader_program, LOG_SIZE, &rLength, elog);
dbpf(10, "Link log: \n %s \n", elog);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
setupBox();
GLfloat vd[6*5*6];
for(int pi=0; pi<6; pi++)
{
vd[pi*30+ 0] = pv[ p[pi].v[0] ].x;
vd[pi*30+ 1] = pv[ p[pi].v[0] ].y;
vd[pi*30+ 2] = pv[ p[pi].v[0] ].z;
vd[pi*30+ 3] = 0.0;
vd[pi*30+ 4] = 1.0;
vd[pi*30+ 5] = pv[ p[pi].v[1] ].x;
vd[pi*30+ 6] = pv[ p[pi].v[1] ].y;
vd[pi*30+ 7] = pv[ p[pi].v[1] ].z;
vd[pi*30+ 8] = 0.0;
vd[pi*30+ 9] = 0.0;
vd[pi*30+10] = pv[ p[pi].v[2] ].x;
vd[pi*30+11] = pv[ p[pi].v[2] ].y;
vd[pi*30+12] = pv[ p[pi].v[2] ].z;
vd[pi*30+13] = 1.0;
vd[pi*30+14] = 0.0;
vd[pi*30+15] = pv[ p[pi].v[0] ].x;
vd[pi*30+16] = pv[ p[pi].v[0] ].y;
vd[pi*30+17] = pv[ p[pi].v[0] ].z;
vd[pi*30+18] = 0.0;
vd[pi*30+19] = 1.0;
vd[pi*30+20] = pv[ p[pi].v[2] ].x;
vd[pi*30+21] = pv[ p[pi].v[2] ].y;
vd[pi*30+22] = pv[ p[pi].v[2] ].z;
vd[pi*30+23] = 1.0;
vd[pi*30+24] = 0.0;
vd[pi*30+25] = pv[ p[pi].v[3] ].x;
vd[pi*30+26] = pv[ p[pi].v[3] ].y;
vd[pi*30+27] = pv[ p[pi].v[3] ].z;
vd[pi*30+28] = 1.0;
vd[pi*30+29] = 1.0;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*5*6, vd, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
tex_Box = generateTexture();
tex_Norm = generateTexture();
}
void setupBox()
{
for (int z=0;z<2;z++)
for (int y=0;y<2;y++)
for (int x=0;x<2;x++)
{
pv[x+y*2+z*4].x = -1.0+x;
pv[x+y*2+z*4].y = -1.0+y;
pv[x+y*2+z*4].z = -1.0+z;
}
p[0].fillverts (0, 1, 3, 2); // above
p[1].fillverts (4, 5, 1, 0); // behind
p[2].fillverts (6, 7, 3, 2); // in front
p[3].fillverts (5, 7, 3, 1); // right
p[4].fillverts (0, 2, 6, 4); // left
p[5].fillverts (7, 6, 4, 5); // below
}
unsigned int generateTexture()
{
BYTE data[128*128*3];
unsigned int id;
for (int x=0;x<128;x++)
for (int y=0;y<128;y++)
{
data[y*128*3+x*3+0] = x; // Red
data[y*128*3+x*3+1] = y; // Green
data[y*128*3+x*3+2] = 128-(abs(64-x)+abs(64-y)); // Blue
}
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}
void mainloop()
{
while(bQuit == false)
{
handle_inputs();
updateScreen();
angle += 1.5f;
Sleep(50);
}
}
void handle_inputs()
{
SDL_PumpEvents();
Uint8 * keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_ESCAPE]) bQuit = true;
}
void updateScreen()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt (2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// use the shader program
glUseProgram(shader_program);
// bind the vao
glBindVertexArray(vao);
// rotation
glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis
glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis
// bind texture
glActiveTexture(GL_TEXTURE0);
int loc = glGetUniformLocation(shader_program, "tex");
glUniform1i(loc, 0);
glBindTexture(GL_TEXTURE_2D, tex_Box);
// bind normal texture
glActiveTexture(GL_TEXTURE1);
loc = glGetUniformLocation(shader_program, "tex_norm");
glUniform1i(loc, 1);
glBindTexture(GL_TEXTURE_2D, tex_Norm);
// draw
glDrawArrays(GL_TRIANGLES, 0, 6*6);
// cleanup
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glUseProgram(0);
SDL_GL_SwapBuffers();
}
void clean_up()
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDetachShader(shader_program, vertex_shader);
glDetachShader(shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDeleteProgram(shader_program);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
glDeleteTextures(1, &tex_Box);
glDeleteTextures(1, &tex_Norm);
SDL_Quit();
}
void dbpf(int t, const char * msg, ...)
{
va_start(m, msg);
if (t >= db_threashold) vfprintf(stderr, msg, m);
va_end(m);
}

OpenGL help translate cube

I have the sample code of drawing a cube. How can I draw other cubes at different positions (using translation matrices) to be able to draw a tetris of which's engine I have.
#include <glf.hpp>
#include <GL/freeglut.h>
#include <camera.h>
#define kEpsilon 1.0e-6f
#define kPI 3.1415926535897932384626433832795f
#define kHalfPI 1.5707963267948966192313216916398f
#define kTwoPI 2.0f*kPI
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
namespace
{
//path to shader files
std::string const SHADER_VERT_SOURCE("../GL3_init/Basic.vsh"); //// relative to
std::string const SHADER_FRAG_SOURCE("../GL3_init/Basic.fsh"); //// the executable path
//cube data
namespace cube {
// (6 faces)(2 triangles/face)(3 vertices/triangle)
const int NumVertices = 36;
glm::vec4 points[NumVertices];
glm::vec4 colors[NumVertices];
// Vertices positions of a unit cube centered at origin
glm::vec4 vertex_positions[8] = {
glm::vec4( -0.5, -0.5, 0.5, 1.0),
glm::vec4( -0.5, 0.5, 0.5, 1.0),
glm::vec4( 0.5, 0.5, 0.5, 1.0),
glm::vec4( 0.5, -0.5, 0.5, 1.0),
glm::vec4( -0.5, -0.5, -0.5, 1.0),
glm::vec4( -0.5, 0.5, -0.5, 1.0),
glm::vec4( 0.5, 0.5, -0.5, 1.0),
glm::vec4( 0.5, -0.5, -0.5, 1.0)
};
// RGBA colors
glm::vec4 vertex_colors[8] = {
glm::vec4( 0.0, 0.0, 0.0, 1.0),//black
glm::vec4( 1.0, 0.0, 0.0, 1.0),//red
glm::vec4( 1.0, 1.0, 0.0, 1.0),//yellow
glm::vec4( 0.0, 1.0, 0.0, 1.0),//green
glm::vec4( 0.0, 0.0, 1.0, 1.0),//blue
glm::vec4( 1.0, 0.0, 1.0, 1.0),//magenta
glm::vec4( 1.0, 1.0, 1.0, 1.0),//white
glm::vec4( 0.0, 1.0, 1.0, 1.0) //cyan
};
// quad() generates two triangles for each face and assigns colors to the vertices
int Index = 0;
void quad( int a, int b, int c, int d )
{
colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
colors[Index] = vertex_colors[b]; points[Index] = vertex_positions[b]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
colors[Index] = vertex_colors[d]; points[Index] = vertex_positions[d]; Index++;
}
// generate 12 triangles: 36 vertices and 36 colors
void colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
}
//OpenGL Objects
GLuint vao;
GLuint buffer;
GLuint program;
//window
int width = 800;
int height = 600;
//MVP
glm::mat4 mProjection = glm::perspective(60.0f, float(width) / height, 0.1f, 1000.0f);
Camera camera(glm::vec3(0.0f, 1.0f,-3.0f), glm::vec3(0.0f,0.0f,0.0f), glm::vec3(0.0f,1.0f,0.0f), mProjection);
//uniform variables
GLuint uMVP;
}
//create, compile and link shaders
bool initProgram()
{
bool Validated(true);
GLuint VertShaderName = glf::createShader(GL_VERTEX_SHADER, SHADER_VERT_SOURCE);
GLuint FragShaderName = glf::createShader(GL_FRAGMENT_SHADER, SHADER_FRAG_SOURCE);
program = glCreateProgram();
glAttachShader(program, VertShaderName);
glAttachShader(program, FragShaderName);
glLinkProgram(program);
glDeleteShader(VertShaderName);
glDeleteShader(FragShaderName);
Validated = Validated && glf::checkProgram(program);
if(Validated)
{
glUseProgram(program);
//Associate uniforms
uMVP = glGetUniformLocation( program, "MVP");
Validated = Validated && glf::checkError("initProgram - stage");
}
}
// Create and initialize buffer object
bool initBuffer()
{
bool Validated(true);
glGenBuffers(1,&buffer);
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(cube::points) + sizeof(cube::colors),NULL,GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cube::points), cube::points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(cube::points), sizeof(cube::colors), cube::colors);
return Validated;
}
// Create and bind vertex array object. Set pointer to vertex attributes
bool initVertexArray()
{
bool Validated(true);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
GLuint vPosition = glGetAttribLocation( program,"vPosition" );
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(cube::points)) );
return Validated;
}
// Setup GL state
bool beginGL()
{
bool Validated(true);
//setup the cube
cube::colorcube();
Validated = initProgram();
if(Validated)
Validated = initBuffer();
if(Validated)
Validated = initVertexArray();
return Validated;
}
// Free memory
void endGL()
{
glDeleteBuffers(1,&buffer);
glDeleteProgram(program);
glDeleteVertexArrays(1, &vao);
}
///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearBufferfv(GL_COLOR, 0, &glm::vec4(0.4f, 0.4f, 0.4f, 1.0f)[0]);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glEnable(GL_MULTISAMPLE);
//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
//setup Model View Projection
glm::mat4 mMVP = camera.getprojection()*camera.ViewMatrix();
glProgramUniformMatrix4fv(program, uMVP, 1, GL_FALSE, glm::value_ptr(mMVP));
//Draw Cube
glDrawArrays(GL_TRIANGLES,0,cube::NumVertices);
// Flush drawing commands
glutSwapBuffers();
// Refresh the Window
glutPostRedisplay();
glDisable(GL_MULTISAMPLE);
}
///////////////////////////////////////////////////////////////////////////////
// A normal ASCII key has been pressed.
// In this case, space bar is pressed
void KeyPressFunc(unsigned char key, int x, int y)
{
switch(key)
{
// controls for camera
// add up/down and left/right controls
case 'L': camera.slide(.2, 0, 0); break;// slide camera right
case 'L' + 32: camera.slide(-0.2, 0, 0); break; // slide camera left
case 'U': camera.slide(0, -0.2, 0); break;// slide camera down
case 'U' + 32: camera.slide(0, 0.2, 0); break; // slide camera up
case 'F': camera.slide(0,0, 0.2); break; // slide camera forward
case 'F' + 32: camera.slide(0,0,-0.2); break; //slide camera back
// add pitch controls
case 'P': camera.pitch(-1.0); break;
case 'P' + 32: camera.pitch( 1.0); break;
// add yaw controls
case 'Y': camera.yaw(-1.0); break;
case 'Y' + 32: camera.yaw( 1.0); break;
// add roll controls
case 'R': camera.roll(1.0); break;
case 'R' + 32: camera.roll(-1.0); break;
// close with Esc
case 27: exit(0); break;
}
}
//////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
width = w; height = h;
glViewport(0, 0, w, h);
mProjection = glm::perspective(60.0f, float(width) / height, 0.1f, 1000.0f);
camera.setprojection(mProjection);
}
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(width, height);
glutCreateWindow("3D Demo");
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return 1;
}
if(beginGL()){
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(KeyPressFunc);
glutDisplayFunc(RenderScene);
glutCloseFunc(endGL);
glutMainLoop();
return 0;
}
return 1;
}
In RenderScene you can play with the following lines in order to draw multiple cubes :
glm::mat4 mMVP = camera.getprojection()*camera.ViewMatrix();
for(int i = 0; i < 10; i++)
{
glm::mat4 finalM = mMVP * a_function_that_creates_a_translation_matrix(x, y, z);
glProgramUniformMatrix4fv(program, uMVP, 1, GL_FALSE, glm::value_ptr(finalM));
glDrawArrays(GL_TRIANGLES,0,cube::NumVertices);
}

Generating a Sphere

I'am trying to draw a icosahedron using OpenGL 3.3+ so i may subdivided later on to make it a sphere, but I keep getting this error in VS2010 Express:
Stack around the variable '_vertices' was corrupted
Here is the code:
#include "Angel.h"
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
unsigned FrameCount = 0;
/*Default values used to draw the object*/
float X = 0.525731112119133606f;
float Z = 0.850650808352039932f;
GLuint
VertexShaderId,
FragmentShaderId,
ProgramId,
VaoId,
VboId,
ColorBufferId,
IndexBufferId;
const GLchar* VertexShader =
{
"#version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 400\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = vec4( 0.0, 0.0, 1.0, 1.0 );\n"\
"}\n"
};
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(4, 0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);
if(WindowHandle < 1) {
exit(EXIT_FAILURE);
}
glutReshapeFunc(ResizeFunction);
glutDisplayFunc(RenderFunction);
glutIdleFunc(IdleFunction);
glutTimerFunc(0, TimerFunction, 0);
glutCloseFunc(Cleanup);
}
void RenderFunction(void)
{
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 60, GL_UNSIGNED_BYTE, (GLvoid*)0);
glutSwapBuffers();
glutPostRedisplay();
}
void CreateVBO(void)
{
/*Starting points*/
GLfloat Vertices[][4] =
{{-X,0.0f,Z, 1.0}, {X,0.0f,Z, 1.0}, {-X,0.0f,-Z, 1.0}, {X,0.0f,-Z, 1.0},
{0.0f,Z,X, 1.0}, {0.0f,Z,-X, 1.0}, {0.0f,-Z,X, 1.0}, {0.0f,-Z,-X, 1.0},
{Z,X,0.0f, 1.0}, {-Z,X,0.0f, 1.0}, {Z,-X,0.0f, 1.0}, {-Z,-X,0.0f, 1.0}};
/*Incdices on how to draw the object using triangles*/
GLubyte Indices[] =
{1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4,
1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2,
3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0,
10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7};
/*Filling up the points which i need to draw from the start*/
GLfloat _vertices[60];
for (int i = 0; i < 60; ++i) {
_vertices[(3*i)+0] = Vertices[Indices[i]][0];
_vertices[(3*i)+1] = Vertices[Indices[i]][1];
_vertices[(3*i)+2] = Vertices[Indices[i]][2];
}
/*End of nodes generation*/
GLenum ErrorCheckValue = glGetError();<br/>
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);<br/>
glGenBuffers(1, &VboId);
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glGenBuffers(1, &IndexBufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
exit(-1);
}
}
Note: I only put the function of drawing and not everything,and that without using the Indices array it would draw some weird stuff. Thanks
for (int i = 0; i < 60; ++i) {
should be
for (int i = 0; i < 20; ++i) {
Otherwise, you're going out of bounds and modifying memory outside of the array, hence, the stack around the array is being corrupted.
You're writing out of array bounds. _vertices is an array of 60 GLfloats, but you're accessing it in the range 0 .. 3*59 + 2.