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.
Related
In order to understand how to use two buffers and binding it to vao i am trying to display a triangle with some color. I am getting an error like this
First-chance exception at 0x00000000 in ConsoleApplication12.exe: 0xC0000005: Access violation executing location 0x00000000.
When i try to debug, this error is caused by the line in the code
glCreateVertexArrays(1, &vao);
I did initialized vao, but i do not understand why the error occurred. Please help me..
Here is the code
#include <stdlib.h>
#include<iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "glm/glm.hpp"
#define BUFFER_OFFSET(offset) ((GLvoid *) offset)
GLuint program;
static int timeFor =0;
GLuint vPos;
GLuint buffer[2];
GLuint vao = 0;
void init()
{
static const GLfloat positions[] = { 0.1f, 0.2f, 0.3f, 0.0f};
static const GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 1.0f};
glCreateVertexArrays(1, &vao);
glCreateBuffers(2, &buffer[0]);
glNamedBufferStorage(buffer[0], sizeof(positions), positions, 0);
glVertexArrayVertexBuffer(vao, 0, buffer[0], 0, sizeof(glm::vec4));
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 0, 0);
glNamedBufferStorage(buffer[1], sizeof(colors), colors, 0);
glVertexArrayVertexBuffer(vao, 1, buffer[1], 0, sizeof(glm::vec4));
glVertexArrayAttribFormat(vao, 1, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 1, 1);
const char* vSource = {
"#version 330\n"
"layout (location = 0) in vec4 offset;"
"layout (location = 1) in vec4 color;"
"out vec4 fColor;"
"void main() {"
"const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0), vec4( -0.25, -0.25, 0.5, 1.0), vec4( 0.25, 0.25, 0.5, 1.0));"
"gl_Position = vertices[gl_VertexID] + offset;"
"fColor = color;"
"}"
};
const char* fSource = {
"#version 330\n"
"in vec4 fColor;"
"out vec4 fragColor;"
"void main() {"
"fragColor = fColor;"
"}"
};
GLuint vShader, fShader;
vShader = glCreateShader(GL_VERTEX_SHADER);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader, 1, &vSource, NULL);
glShaderSource(fShader, 1, &fSource, NULL);
glCompileShader(vShader);
glCompileShader(fShader);
program = glCreateProgram();
glAttachShader(program, vShader);
glAttachShader(program, fShader);
glLinkProgram(program);
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
glewInit();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
I checked my openGL version its 4.4, in which glCreateVertexArrays is not supported instead of that glGenVertexArrays must be used.
I have a Mac running OS X Yosemite with GLFW 3 and OpenGL 4.1. I've got this program:
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/string_cast.hpp>
#include <stdio.h>
#include "myglutils.hpp"
int main() {
if (!setupGLFW()) return 1;
setupApple();
GLFWwindow* window = glfwCreateWindow(640, 480, "Perspective", 0, NULL);
if (!window) {
fprintf(stderr, "Failed to create window.\n");
glfwTerminate();
return 0;
}
glfwMakeContextCurrent(window);
if (!setupGLEW()) return 1;
glClearColor(0.2, 0.0, 0.8, 1.0);
const GLfloat vertices[] = {
-1.0, -1.0,
1.0, -1.0,
0.0, 1.0
};
const GLchar* vert_shader =
"#version 410 core\n"
"in vec2 pos;"
"uniform mat4 MVP;"
"void main() {"
" gl_Position = MVP * vec4(pos, 0.0, 1.0);"
"}";
const GLchar* frag_shader =
"#version 410 core\n"
"out vec4 color;"
"void main() {"
" color = vec4(1.0, 0.0, 0.0, 1.0);"
"}";
GLuint shader = getShader(vert_shader, frag_shader);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
GLuint MVPID = glGetUniformLocation(shader, "MVP");
glm::mat4 perspective = glm::perspective(45.0, 4.0 / 3.0, 0.1, 100.0);
glm::mat4 view = glm::lookAt(glm::vec3(4.0, 3.0, 3.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
glm::mat4 MVP = perspective * view;
while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS) {
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glUniformMatrix4fv(MVPID, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &vao);
glDeleteProgram(shader);
glfwTerminate();
return 0;
}
The functions setupGLFW(), setupApple(), and setupGLEW() aren't the problem. Neither is getShader(). I feel like my error is something silly like forgetting a simple OpenGL function call. What I'm trying to do is draw a triangle at a 3D angle.
Note: this program compiles perfectly, but only displays an empty blue screen.
There are a number of issues in this code. The main one is that you never enable the vertex attribute array. You will need to add a glEnableVertexAttribArray() call in the setup code:
glBindVertexArray(vao);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
Also, the arguments to glDrawArrays() are not correct:
glDrawArrays(GL_TRIANGLES, 0, 6);
The 3rd argument is the number of vertices. Since you only have 3 vertices, it should be:
glDrawArrays(GL_TRIANGLES, 0, 3);
Also, unless this is taken care of in code you did not post, you need to make sure that the attribute location you are using matches the program. You use 0 in the code, but you can't count on the location being zero without any further action. The easiest way to fix this is to use a location layout qualifier in the shader code:
"layout(location=0) in vec2 pos;"
This will set the location to 0, matching your code.
I'm completely new to OpenGL and am having trouble on binding texture and shaders to VBOs works.
Here's my code.
static const char *vertexShaderSource =
"attribute highp vec3 posAttr;\n"
"attribute highp vec2 texAttr;\n"
"varying highp vec2 texCoord;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" texCoord = texAttr;\n"
" gl_Position = matrix * vec4(posAttr, 1.0);\n"
"}\n";
static const char *fragmentShaderSource =
"varying highp vec2 texCoord;\n"
"uniform sampler2D gSampler;\n"
"void main() {\n"
//" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" //it work
" gl_FragColor = texture2D(gSampler, texCoord);\n" //it not work
"}\n";
create buffers.
void TriangleWindow::createVertexBuffer()
{
GLfloat vertices[] = {
1.0f,1.0f,0.0f, 0.0f,0.0f,
0.0f,1.0f,1.0f, 0.5f,0.0f,
1.0f,0.0f,1.0f, 1.0f,0.0f,
0.5f,0.0f,0.0f, 0.5f,1.0f
};
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
qDebug()<<"sizeof(vertices) is "<<sizeof(vertices);
}
void TriangleWindow::createIndexBuffer()
{
GLuint indexs[] = {
0,1,3,
0,2,1,
0,3,2,
1,3,2
};
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW);
qDebug()<<"sizeof(indexs) is "<<sizeof(indexs);
}
void TriangleWindow::createTextureBuffer()
{
QString resPath = "/Users/luxiaodong/Project/Demo/OpenGLES/res";
QString imgPath = QString("%1/test.png").arg(resPath);
qDebug()<<imgPath;
QImage image = QImage(imgPath).convertToFormat( QImage::Format_RGBA8888 );
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexParameterf(m_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(m_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(m_tex, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image.bits() );
//glTexImage2D(GL_TEXTURE_2D, 0, 4, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
}
initialize
void TriangleWindow::initialize()
{
createVertexBuffer();
createIndexBuffer();
createTextureBuffer();
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_texAttr = m_program->attributeLocation("texAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
m_gSampler = m_program->uniformLocation("gSampler");
m_program->setUniformValue(m_gSampler, 0);
qDebug()<<m_posAttr<<m_texAttr<<m_matrixUniform<<m_gSampler;
}
render
void TriangleWindow::render()
{
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -4);
matrix.rotate(100.0f * m_frame/screen()->refreshRate(), 0, 1, 0);
m_program->setUniformValue(m_matrixUniform, matrix);
m_program->setUniformValue(m_gSampler, 0);
glEnableVertexAttribArray(m_posAttr);
glEnableVertexAttribArray(m_texAttr);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 20, (const GLvoid*)0);
glVertexAttribPointer(m_texAttr, 2, GL_FLOAT, GL_FALSE, 20, (const GLvoid*)12);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_tex);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const GLvoid*)0 );
glDisableVertexAttribArray(m_texAttr);
glDisableVertexAttribArray(m_posAttr);
m_program->release();
++m_frame;
}
I'm not sure what i am doing wrong. I tried different things with the shader but it seems it doesn't matter. in fragmentShader.
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" //it work
" gl_FragColor = texture2D(gSampler, texCoord);\n" //it not work
Is this a problem with the shader I'm using, or is it something else that I'm not understanding?
Either the uniform(gSampler) or attribute(texAttr) should be the reason. To verify texAttr, use this as
gl_FragColor = vec4(texCoord.x,texCoord.y,0.0,1.0);
if your output is in some color then there is no problem in texAttr. I don't see any coding issue for texAttr. Anyway check once.
To verify gSampler, verify the glUniform1i(m_gSampler,unit), the unit should match the value(GL_TEXTURE0) you used to bind before glDrawElement.
This is exercises for my course in computer graphics, but I'm not asking for solutions, just for a way to be able to actually work on the exercises since right now I can't because all the output is producing is black window - I know what it's supposed to produce since I worked on it on school computers and am trying to work on it from home now.
The code works fine on school computers, and I've asked the TAs for help, but they've been unsuccesful so far in locating my problem.
The school computers run on VS 2010 windows 7, while I only have VS 2013 windows 8.1 available. When I opened the project the first time it asked me to convert it to VS2013 etc. and I did so.
I am able to run some other exercises just fine, but I have a problem with all exercises above 2.1.
The code below is from exercise 2.2
// 02561-02-02
#include <iostream>
#include <string>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "Angel.h"
using namespace std;
using namespace Angel;
int WINDOW_WIDTH = 500;
int WINDOW_HEIGHT = 500;
GLuint shaderProgram;
GLuint projectionUniform,
modelViewUniform,
colorUniform;
GLuint positionAttribute;
GLuint unitCubeVertexArrayObject,
axisVertexArrayObject,
vertexBuffer;
const int axisSize = 6;
struct Vertex {
vec4 position;
};
void loadShader();
void display();
GLuint loadBufferData(Vertex* vertices, int vertexCount);
void buildUnitCube() {
const int cubeSize = 8;
Vertex cubeData[cubeSize] = {
{ vec4( 1.0, 1.0, 1.0, 1.0 ) },
{ vec4( 1.0, 0.0, 1.0, 1.0 ) },
{ vec4( 1.0, 1.0, 0.0, 1.0 ) },
{ vec4( 1.0, 0.0, 0.0, 1.0 ) },
{ vec4(-0.0, 1.0, 0.0, 1.0 ) },
{ vec4(-0.0, 0.0, 0.0, 1.0 ) },
{ vec4(-0.0, 1.0, 1.0, 1.0 ) },
{ vec4(-0.0, 0.0, 1.0, 1.0 ) }
};
unitCubeVertexArrayObject = loadBufferData(cubeData, cubeSize);
}
void buildAxis() {
Vertex axisData[axisSize] = {
{vec4(0., 0., 0., 1.0)}, // v0
{vec4(4., 0., 0., 1.0)}, // vx
{vec4(0., 4., 0., 1.0)}, // vy
{vec4(0., 0., 4., 1.0)}, // vz
{vec4(1., 0., 0., 1.0)}, // v0x1
{vec4(1., 3., 0., 1.0)} // vyx1
};
axisVertexArrayObject = loadBufferData(axisData, axisSize);
}
GLuint loadBufferData(Vertex* vertices, int vertexCount) {
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
return vertexArrayObject;
}
void loadShader(){
shaderProgram = InitShader("const-shader.vert", "const-shader.frag", "fragColor");
projectionUniform = glGetUniformLocation(shaderProgram, "projection");
if (projectionUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'projection' uniform."<<endl;
}
modelViewUniform = glGetUniformLocation(shaderProgram, "modelView");
if (modelViewUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'modelView' uniform."<<endl;
}
colorUniform = glGetUniformLocation(shaderProgram, "color");
if (colorUniform == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'color' uniform."<<endl;
}
positionAttribute = glGetAttribLocation(shaderProgram, "position");
if (positionAttribute == GL_INVALID_INDEX) {
cerr << "Shader did not contain the 'position' attribute." << endl;
}
}
void drawWireUnitCube() {
GLuint indices[24] = {
0,1,
1,3,
3,2,
2,0,
4,5,
5,7,
7,6,
6,4,
7,1,
6,0,
4,2,
5,3
};
glBindVertexArray(unitCubeVertexArrayObject);
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, indices);
}
void drawAxis() {
GLuint indices[8] = {
0,1,
0,2,
0,3,
4,5
};
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, indices);
}
void display() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
mat4 projection = Ortho(-6., 6., -6., 6., -6., 10.);
glUniformMatrix4fv(projectionUniform, 1, GL_TRUE, projection);
mat4 modelView(1.0f);
vec4 red(1.0, 0.0, 0.0, 1.0);
glUniform4fv(colorUniform, 1, red);
glUniformMatrix4fv(modelViewUniform, 1, GL_TRUE, modelView);
drawAxis();
// todo multiply model transformations
vec4 white(1.0, 1.0, 1.0, 1.0);
glUniform4fv(colorUniform, 1, white);
glUniformMatrix4fv(modelViewUniform, 1, GL_TRUE, modelView);
drawWireUnitCube();
glutSwapBuffers();
Angel::CheckError();
}
void reshape(int W, int H) {
WINDOW_WIDTH = W;
WINDOW_HEIGHT = H;
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitContextVersion(3, 2);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_3_2_CORE_PROFILE);
glutCreateWindow("02561-02-02");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);
Angel::InitOpenGL();
loadShader();
buildUnitCube();
buildAxis();
Angel::CheckError();
glutMainLoop();
}
Your code requests a Core Profile context:
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
but it's not completely compatible with the Core Profile. In the Core Profile, all vertex data needs to be sourced from buffers. Passing client side arrays for vertex data is not supported anymore. This includes index data. So the following is not allowed:
GLuint indices[8] = {
0,1,
0,2,
0,3,
4,5
};
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, indices);
You need to store the indices in a GL_ELEMENT_ARRAY_BUFFER. Extend the signature of loadBufferData() function to also take index data, and add code to also create an index buffer:
GLuint loadBufferData(Vertex* vertices, int vertexCount
GLuint* indices, int indexCount) {
...
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLuint), indices, GL_STATIC_DRAW);
return vertexArrayObject;
}
Then the draw functions look like this:
glBindVertexArray(axisVertexArrayObject);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_INT, 0);
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);
}