I am trying to generate a terrain from a file, and display it in a window on my screen in openGL. I am getting a seg fault and I've localised it to the glDrawArrays() call in my code.
I might be calling it wrong, or my heightmap may have too many vertices for the way I am calling it.
I will link my code below and put a comment next to the segfault line.
/**
* A typical program flow and methods for rendering simple polygons
* using freeglut and openGL + GLSL
*/
#include <stdio.h>
// GLEW loads OpenGL extensions. Required for all OpenGL programs.
#include <GL/glew.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Utility code to load and compile GLSL shader programs
#include "shader.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
//#define VALS_PER_VERT 3
//#define VALS_PER_COLOUR 4
//#define NUM_VERTS 3 // Total number of vertices to load/render
#define VALS_PER_VERT_HEIGHT 5
#define VALS_PER_COLOUR_HEIGHT 4
#define HEIGHT_VERTS 5 //height map vertices per line
using namespace std;
// Handle to our VAO generated in setShaderData method
//heightmap
unsigned int vertexVaoHandleHeight;
// Handle to our shader program
unsigned int programID;
/**
* Sets the shader uniforms and vertex data
* This happens ONCE only, before any frames are rendered
* #param id, Shader program object to use
* #returns 0 for success, error otherwise
*/
int setShaderData(const unsigned int &id)
{
/*
* What we want to draw
* Each set of 3 vertices (9 floats) defines one triangle
* You can define more triangles to draw here
*/
float heightmapVerts[ HEIGHT_VERTS*VALS_PER_VERT_HEIGHT ] = {
//5
-0.9, -0.6, -0.4, -0.6, -0.9,
-0.2, 0.1, 0.3, 0.1, -0.3,
0, 0.4, 0.8, 0.4, 0,
-0.2, 0.1, 0.3, 0.1, -0.3,
0.5, -0.6, -0.4, -0.6, -0.9,
};
std::cout << "1" << endl;
// Colours for each vertex; red, green, blue and alpha
// This data is indexed the same order as the vertex data, but reads 4 values
// Alpha will not be used directly in this example program
//may cause problems because less numbers
float heightColours[ HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT ] = {
0.8f, 0.7f, 0.5f, 1.0f,
0.3f, 0.7f, 0.1f, 1.0f,
0.8f, 0.2f, 0.5f, 1.0f,
};
std::cout << "2" << endl;
// heightmap stuff ##################################################
// Generate storage on the GPU for our triangle and make it current.
// A VAO is a set of data buffers on the GPU
glGenVertexArrays(1, &vertexVaoHandleHeight);
glBindVertexArray(vertexVaoHandleHeight);
std::cout << "3" << endl;
// Generate new buffers in our VAO
// A single data buffer store for generic, per-vertex attributes
unsigned int bufferHeight[2];
glGenBuffers(2, bufferHeight);
// Allocate GPU memory for our vertices and copy them over
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_VERT_HEIGHT, heightmapVerts, GL_STATIC_DRAW);
// Do the same for our vertex colours
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT, heightColours, GL_STATIC_DRAW);
std::cout << "4" << endl;
// Now we tell OpenGL how to interpret the data we just gave it
// Tell OpenGL what shader variable it corresponds to
// Tell OpenGL how it's formatted (floating point, 3 values per vertex)
int vertLocHeight = glGetAttribLocation(id, "a_vertex");
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
glEnableVertexAttribArray(vertLocHeight);
glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
std::cout << "5" << endl;
// Do the same for the vertex colours
int colourLocHeight = glGetAttribLocation(id, "a_colour");
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
glEnableVertexAttribArray(colourLocHeight);
glVertexAttribPointer(colourLocHeight, VALS_PER_COLOUR_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
// heightmap stuff ##################################################
std::cout << "6" << endl;
// An argument of zero un-binds all VAO's and stops us
// from accidentally changing the VAO state
glBindVertexArray(0);
// The same is true for buffers, so we un-bind it too
glBindBuffer(GL_ARRAY_BUFFER, 0);
std::cout << "7" << endl;
return 0; // return success
}
/**
* Renders a frame of the state and shaders we have set up to the window
* Executed each time a frame is to be drawn.
*/
void render()
{
// Clear the previous pixels we have drawn to the colour buffer (display buffer)
// Called each frame so we don't draw over the top of everything previous
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
std::cout << "8" << endl;
// HEIGHT MAP STUFF ###################################
// Make the VAO with our vertex data buffer current
glBindVertexArray(vertexVaoHandleHeight);
// Send command to GPU to draw the data in the current VAO as triangles
std::cout << "8.5" << endl;
//CRASHES HERE
glDrawArrays(GL_TRIANGLES, 0, /*HEIGHT_VERTS = 5*/ 3);
std::cout << "8.75" << endl;
glBindVertexArray(0); // Un-bind the VAO
std::cout << "9" << endl;
// HEIGHT MAP STUFF ###################################
glutSwapBuffers(); // Swap the back buffer with the front buffer, showing what has been rendered
glFlush(); // Guarantees previous commands have been completed before continuing
}
/**
* Program entry. Sets up OpenGL state, GLSL Shaders and GLUT window and function call backs
* Takes no arguments
*/
int main(int argc, char **argv) {
//READ IN FILE//
std::fstream myfile("heights.csv", std::ios_base::in);
if(!myfile.good()){cout << "file not found" << endl;}
std::vector<float> numbers;
float a;
while (myfile >> a){/*printf("%f ", a);*/
numbers.push_back(a);
}
//for (int i=0; i<numbers.size();i++){cout << numbers[i] << endl;}
getchar();
//READ IN FILE//
// Set up GLUT window
glutInit(&argc, argv); // Starts GLUT systems, passing in command line args
glutInitWindowPosition(100, 0); // Positions the window on the screen relative to top left
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); // Size in pixels
// Display mode takes bit flags defining properties you want the window to have;
// GLUT_RGBA : Set the pixel format to have Red Green Blue and Alpha colour channels
// GLUT_DOUBLE : Each frame is drawn to a hidden back buffer hiding the image construction
// GLUT_DEPTH : A depth buffer is kept so that polygons can be drawn in-front/behind others (not used in this application)
#ifdef __APPLE__
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_3_2_CORE_PROFILE);
#else
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
#endif
glutCreateWindow("Hello World!"); // Makes the actual window and displays
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Sets the (background) colour for each time the frame-buffer (colour buffer) is cleared
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Set up the shaders we are to use. 0 indicates error.
programID = LoadShaders("minimal.vert", "minimal.frag");
if (programID == 0)
return 1;
// Set this shader program in use
// This is an OpenGL state modification and persists unless changed
glUseProgram(programID);
// Set the vertex data for the program
if (setShaderData(programID) != 0)
return 1;
// Render call to a function we defined,
// that is called each time GLUT thinks we need to update
// the window contents, this method has our drawing logic
glutDisplayFunc(render);
// Start an infinite loop where GLUT calls methods (like render)
// set with glut*Func when needed.
// Runs until something kills the window
glutMainLoop();
return 0;
}
The size argument of glVertexAttribPointer() must be 1, 2, 3, or 4. You pass 5 here:
#define VALS_PER_VERT_HEIGHT 5
...
glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
You should always call glGetError() if you have problems with your rendering. The call above will immediately give you a GL_INVALID_VALUE error.
Your code also looks generally inconsistent. In some places, you seem to assume that you have 3 vertices, in others 4, in others 5. Then, as shown above, you have vertices with 5 coordinates, which does not really make any sense. You may want to have a careful look at your own code, and make sure that everything is consistent with what you are trying to do.
Related
I am trying to test how may triangles I can draw on my laptop, so I am doing the following on my system:
OS: Windows 10
CPU: Intel Core i5 5200U
GPU: NVIDIA Geforce 820M
Code:
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 02 - Red triangle", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
// Number of triangles
const int v = 200;
static GLfloat g_vertex_buffer_data[v*9] = {
-1.0f, -1.0f, 1.0f,
0.8f, 0.f, 0.0f,
0.5f, 1.0f, 0.0f,
};
// fill buffer of triangles
for (int i = 9; i < v * 9; i += 9)
{
g_vertex_buffer_data[i] = g_vertex_buffer_data[0];
g_vertex_buffer_data[i+1] = g_vertex_buffer_data[1];
g_vertex_buffer_data[i+2] = g_vertex_buffer_data[2];
g_vertex_buffer_data[i+3] = g_vertex_buffer_data[3];
g_vertex_buffer_data[i+4] = g_vertex_buffer_data[4];
g_vertex_buffer_data[i+5] = g_vertex_buffer_data[5];
g_vertex_buffer_data[i+6] = g_vertex_buffer_data[6];
g_vertex_buffer_data[i+7] = g_vertex_buffer_data[7];
g_vertex_buffer_data[i+8] = g_vertex_buffer_data[8];
}
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
int frameNr = 0;
char text[100];
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, v*3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
//glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
frameNr++;
sprintf_s(text, "%d %d %d", frameNr, clock() / 1000, (frameNr * 1000) / (clock() + 1));
glfwSetWindowTitle(window, text);
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
What wonders me there is that I only get about 80 fps with v = 200 Triangles.
This would be about 16000 Triangles per second what is pretty bad isnt it?
What am I doing wrong here in the code, or can my graphics card really just handle such a low amount of triangles?
How many triangles can a modern gpu like a 1080ti handle (I heard in theory 11 billion ones -although I know in reality it's much lower).
Since I don't yet have enough reputation to comment, let me ask here: How large are your triangles? It's hard to tell without having seen the vertex shader, but assuming those coordinates in your code are directly mapped to normalized device coordinates, your triangle covers a significant part of the screen. If I'm not mistaken, you basically draw the same triangle over and over on top of itself. Thus, you will most likely be fillrate limited. To get more meaningful results, you might rather want to just draw a grid of non-overlapping triangles or at least a random triangle soup instead. To further minimize fillrate and framebuffer bandwidth requirements, you might wanna make sure that depth buffering and blending are turned off.
If you're interested in raw triangles per second, why do you enable MSAA? Doing so just artificially amplifies rasterizer load. As others have noted too, V-Sync is likely switched off as 80 Hz would be a rather weird refresh rate, but better make sure and explicitly switch it off via glfwSwapInterval(0). Rather than estimating total frame time like you do, you might want to consider measuring the actual drawing time on the GPU using a GL_TIME_ELAPSED query.
Here is the output of my program.
Here is my code
#include <cstdio> // for C++ i/o
#include <iostream>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#define PI 3.14159265
#define MAX_SLICES 32
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 0.5
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
// global variables
GLfloat g_vertices[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
GLuint g_VBO = 0; // identifiers
GLuint g_VAO = 0;
GLuint g_shaderProgramID = 0;
void generate_circle()
{
float angle = PI*2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices+2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices[index + 2] = 0.0f;
// update to next angle
angle += PI*2 / static_cast<float>(g_slices);
}
}
static void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("SimpleVS.vert", "SimpleFS.frag");
// generate vertices of triangle fan
generate_circle();
// create VBO and buffer the data
glGenBuffers(1, &g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*(g_slices + 2), g_vertices, GL_STATIC_DRAW);
// create VAO and specify VBO data
glGenVertexArrays(1, &g_VAO);
glBindVertexArray(g_VAO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
glEnableVertexAttribArray(0); // enable vertex attributes
}
// function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT); // clear colour buffer
glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program
glBindVertexArray(g_VAO); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices+2); // display the vertices based on the primitive type
glFlush(); // flush the pipeline
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
glfwSetErrorCallback(error_callback); // set error callback function
// initialise GLFW
if(!glfwInit())
{
// if failed to initialise GLFW
exit(EXIT_FAILURE);
}
// minimum OpenGL version 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// create a window and its OpenGL context
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "DemoCode", NULL, NULL);
// if failed to create window
if(window == NULL)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window); // set window context as the current context
glfwSwapInterval(1); // swap buffer interval
// initialise GLEW
if(glewInit() != GLEW_OK)
{
// if failed to initialise GLEW
cerr << "GLEW initialisation failed" << endl;
exit(EXIT_FAILURE);
}
// set key callback function
glfwSetKeyCallback(window, key_callback);
// initialise rendering states
init();
// the rendering loop
while(!glfwWindowShouldClose(window))
{
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_VBO);
glDeleteVertexArrays(1, &g_VAO);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
I want to get rid of the red line coming out from the axis. I just want a hollow circle.
I'm using GL_LINE_LOOP to draw my arrays. Am I using the wrong primitive?
I have tried adjusting the coordinates in g_vertices and it does make the line smaller, but when I increase the radius of the circle, the line appears again.
You are drawing a GL_LINE_LOOP:
see Khronos group OGL Primitive documentation:
GL_LINE_LOOP: As line strips, except that the first and last vertices are also used as a line.
Thus, you get n lines for n input vertices. If the user only specifies 1 vertex, the drawing command is ignored.
The line between the first and last vertices happens after all of the previous lines in the sequence.
You initilize the first and the second vertex position with (0, 0, 0):
GLfloat g_vertices[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
And then you add the vertices for the circle, because your loop starts as the index starts at index 2:
for (int i = 2; i < g_slices+2; i++)
{
......
}
What you are drawing is a line from the center to the first point on the circle.
Then you draw the circle. Finally the last vertex position (on the circle) is connected to the first, which is the center point of the circle.
You have to skip the 2 vertices at the begin of the list. You do not have to initialize the first two vertices and you can start the loop at 0.
See the code above:
Definitions and global variables:
#define MAX_SLICES 32
#define MAX_VERTICES MAX_SLICES*3
GLfloat g_vertices_circle[MAX_VERTICES];
GLuint g_slices = MAX_SLICES;
Create the vertex position and color attribute array
for (int i = 0; i < g_slices; i++)
{
float angle = (float)PI * 2.0f * (float)i / float(g_slices);
int index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
}
Set up vertex buffer object:
glGenBuffers(1, &g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * g_slices, g_vertices, GL_STATIC_DRAW);
And finally the drawing:
glDrawArrays( GL_LINE_LOOP, 0, g_slices );
Here
GLfloat g_vertices[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
And here:
g_vertices[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices+2; i++)
Vertex 0 is always (0, 0, 0).
I have a file which has terrain coordinates in it like this:
//The first value is how many rows and columns the map has (assuming its a square)
5
-0.9 -0.6 -0.4 -0.6 -0.9
-0.2 0.1 0.3 0.1 -0.3
0 0.4 0.8 0.4 0
-0.2 0.1 0.3 0.1 -0.3
0.5 -0.6 -0.4 -0.6 -0.9
I have put these values into a vector(float) and now need to format it so that I can render the vertices and make a terrain. How do I go about doing this?
std::fstream myfile("heights.csv", std::ios_base::in);
std::vector<float> numbers;
float a;
while (myfile >> a){/*printf("%f ", a);*/
numbers.push_back(a);
}
Just for reference, here is the rest of my code, it's basically code for rending 2 triangles on the screen, which I plan to remove later (just trying to learn)
/**
* A typical program flow and methods for rendering simple polygons
* using freeglut and openGL + GLSL
*/
#include <stdio.h>
// GLEW loads OpenGL extensions. Required for all OpenGL programs.
#include <GL/glew.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Utility code to load and compile GLSL shader programs
#include "shader.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
#define VALS_PER_VERT 3
#define VALS_PER_COLOUR 4
#define NUM_VERTS 3 // Total number of vertices to load/render
using namespace std;
// Handle to our VAO generated in setShaderData method
unsigned int vertexVaoHandle;
unsigned int vertexVaoHandle2;
// Handle to our shader program
unsigned int programID;
/**
* Sets the shader uniforms and vertex data
* This happens ONCE only, before any frames are rendered
* #param id, Shader program object to use
* #returns 0 for success, error otherwise
*/
int setShaderData(const unsigned int &id)
{
/*
* What we want to draw
* Each set of 3 vertices (9 floats) defines one triangle
* You can define more triangles to draw here
*/
float vertices[ NUM_VERTS*VALS_PER_VERT ] = {
-0.5f, -0.5f, -0.0f, // Bottom left
0.5f, -0.5f, -0.0f, // Bottom right
0.0f, 0.5f, -0.0f // Top
};
float vertices2[ NUM_VERTS*VALS_PER_VERT ] = {
-0.9f, -0.9f, -0.0f, // Bottom left
0.9f, -0.9f, -0.0f, // Bottom right
0.9f, 0.5f, -0.0f // Top
};
float heightmap[ NUM_VERTS*VALS_PER_VERT ] = {
-0.9f, -0.9f, -0.0f, // Bottom left
0.9f, -0.9f, -0.0f, // Bottom right
0.9f, 0.5f, -0.0f
};
// Colours for each vertex; red, green, blue and alpha
// This data is indexed the same order as the vertex data, but reads 4 values
// Alpha will not be used directly in this example program
float colours[ NUM_VERTS*VALS_PER_COLOUR ] = {
0.8f, 0.7f, 0.5f, 1.0f,
0.3f, 0.7f, 0.1f, 1.0f,
0.8f, 0.2f, 0.5f, 1.0f,
};
float colours2[ NUM_VERTS*VALS_PER_COLOUR ] = {
0.8f, 0.7f, 0.5f, 1.0f,
0.3f, 0.7f, 0.1f, 1.0f,
0.8f, 0.2f, 0.5f, 1.0f,
};
// Generate storage on the GPU for our triangle and make it current.
// A VAO is a set of data buffers on the GPU
glGenVertexArrays(1, &vertexVaoHandle);
glBindVertexArray(vertexVaoHandle);
// Generate new buffers in our VAO
// A single data buffer store for generic, per-vertex attributes
unsigned int buffer[2];
glGenBuffers(2, buffer);
// Allocate GPU memory for our vertices and copy them over
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTS*VALS_PER_VERT, vertices, GL_STATIC_DRAW);
// Do the same for our vertex colours
glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTS*VALS_PER_COLOUR, colours, GL_STATIC_DRAW);
// Now we tell OpenGL how to interpret the data we just gave it
// Tell OpenGL what shader variable it corresponds to
// Tell OpenGL how it's formatted (floating point, 3 values per vertex)
int vertLoc = glGetAttribLocation(id, "a_vertex");
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glEnableVertexAttribArray(vertLoc);
glVertexAttribPointer(vertLoc, VALS_PER_VERT, GL_FLOAT, GL_FALSE, 0, 0);
// Do the same for the vertex colours
int colourLoc = glGetAttribLocation(id, "a_colour");
glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
glEnableVertexAttribArray(colourLoc);
glVertexAttribPointer(colourLoc, VALS_PER_COLOUR, GL_FLOAT, GL_FALSE, 0, 0);
// An argument of zero un-binds all VAO's and stops us
// from accidentally changing the VAO state
glBindVertexArray(0);
// The same is true for buffers, so we un-bind it too
glBindBuffer(GL_ARRAY_BUFFER, 0);
// SECOND TRI
// Generate storage on the GPU for our triangle and make it current.
// A VAO is a set of data buffers on the GPU
glGenVertexArrays(1, &vertexVaoHandle2);
glBindVertexArray(vertexVaoHandle2);
// Generate new buffers in our VAO
// A single data buffer store for generic, per-vertex attributes
unsigned int buffer2[2];
glGenBuffers(2, buffer2);
// Allocate GPU memory for our vertices and copy them over
glBindBuffer(GL_ARRAY_BUFFER, buffer2[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTS*VALS_PER_VERT, vertices2, GL_STATIC_DRAW);
// Do the same for our vertex colours
glBindBuffer(GL_ARRAY_BUFFER, buffer2[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTS*VALS_PER_COLOUR, colours2, GL_STATIC_DRAW);
// Now we tell OpenGL how to interpret the data we just gave it
// Tell OpenGL what shader variable it corresponds to
// Tell OpenGL how it's formatted (floating point, 3 values per vertex)
int vertLoc2 = glGetAttribLocation(id, "a_vertex");
glBindBuffer(GL_ARRAY_BUFFER, buffer2[0]);
glEnableVertexAttribArray(vertLoc2);
glVertexAttribPointer(vertLoc2, VALS_PER_VERT, GL_FLOAT, GL_FALSE, 0, 0);
// Do the same for the vertex colours
int colourLoc2 = glGetAttribLocation(id, "a_colour");
glBindBuffer(GL_ARRAY_BUFFER, buffer2[1]);
glEnableVertexAttribArray(colourLoc2);
glVertexAttribPointer(colourLoc2, VALS_PER_COLOUR, GL_FLOAT, GL_FALSE, 0, 0);
// An argument of zero un-binds all VAO's and stops us
// from accidentally changing the VAO state
glBindVertexArray(0);
// The same is true for buffers, so we un-bind it too
glBindBuffer(GL_ARRAY_BUFFER, 0);
return 0; // return success
}
/**
* Renders a frame of the state and shaders we have set up to the window
* Executed each time a frame is to be drawn.
*/
void render()
{
// Clear the previous pixels we have drawn to the colour buffer (display buffer)
// Called each frame so we don't draw over the top of everything previous
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
// Make the VAO with our vertex data buffer current
glBindVertexArray(vertexVaoHandle);
// Send command to GPU to draw the data in the current VAO as triangles
glDrawArrays(GL_TRIANGLES, 0, NUM_VERTS);
glBindVertexArray(0); // Un-bind the VAO
// SECOND TRIANGLE
// Make the VAO with our vertex data buffer current
glBindVertexArray(vertexVaoHandle2);
// Send command to GPU to draw the data in the current VAO as triangles
glDrawArrays(GL_TRIANGLES, 0, NUM_VERTS);
glBindVertexArray(0); // Un-bind the VAO
// XXXXXXXX
glutSwapBuffers(); // Swap the back buffer with the front buffer, showing what has been rendered
glFlush(); // Guarantees previous commands have been completed before continuing
}
/**
* Program entry. Sets up OpenGL state, GLSL Shaders and GLUT window and function call backs
* Takes no arguments
*/
int main(int argc, char **argv) {
//READ IN FILE//
std::fstream myfile("heights.csv", std::ios_base::in);
std::vector<float> numbers;
float a;
while (myfile >> a){/*printf("%f ", a);*/
numbers.push_back(a);
}
for (int i=0; i<numbers.size();i++){cout << numbers[i] << endl;}
getchar();
//READ IN FILE//
// Set up GLUT window
glutInit(&argc, argv); // Starts GLUT systems, passing in command line args
glutInitWindowPosition(100, 0); // Positions the window on the screen relative to top left
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); // Size in pixels
// Display mode takes bit flags defining properties you want the window to have;
// GLUT_RGBA : Set the pixel format to have Red Green Blue and Alpha colour channels
// GLUT_DOUBLE : Each frame is drawn to a hidden back buffer hiding the image construction
// GLUT_DEPTH : A depth buffer is kept so that polygons can be drawn in-front/behind others (not used in this application)
#ifdef __APPLE__
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_3_2_CORE_PROFILE);
#else
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
#endif
glutCreateWindow("Hello World!"); // Makes the actual window and displays
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Sets the (background) colour for each time the frame-buffer (colour buffer) is cleared
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// Set up the shaders we are to use. 0 indicates error.
programID = LoadShaders("minimal.vert", "minimal.frag");
if (programID == 0)
return 1;
// Set this shader program in use
// This is an OpenGL state modification and persists unless changed
glUseProgram(programID);
// Set the vertex data for the program
if (setShaderData(programID) != 0)
return 1;
// Render call to a function we defined,
// that is called each time GLUT thinks we need to update
// the window contents, this method has our drawing logic
glutDisplayFunc(render);
// Start an infinite loop where GLUT calls methods (like render)
// set with glut*Func when needed.
// Runs until something kills the window
glutMainLoop();
return 0;
}
Actually , i could not understand what do you want to do. But maybe this helps.
Read first line and get row,col size. Allocate multidimensional array. Go ahead to read next lines. Put the values inside array that are extracted from lines.
std::ifstream file( "heights.csv" );
std::string line;
getline(file , line);
int ColRowSize;
line >> ColRowSize;
/// allocate map
float** data = malloc(ColRowSize * sizeof(float *));
for(i = 0; i < ColRowSize; i++)
{
array[i] = malloc(ColRowSize * sizeof(float));
}
/// read from file
for(i = 0; i < ColRowSize; i++)
{
getline(file , line);
for(j = 0; j < ColRowSize; j++)
line >> data[i][j];
}
I am trying to create a heightmap from 25 float values like so:
#define HEIGHT_VERTS 5
#define VALS_PER_VERT_HEIGHT 5
float heightmapVerts[ HEIGHT_VERTS*VALS_PER_VERT_HEIGHT ] = {
//5
-0.9, -0.6, -0.4, -0.6, -0.9,
-0.2, 0.1, 0.3, 0.1, -0.3,
0, 0.4, 0.8, 0.4, 0,
-0.2, 0.1, 0.3, 0.1, -0.3,
0.5, -0.6, -0.4, -0.6, -0.9,
};
I am getting a segmentation fault when calling:
glDrawArrays(GL_TRIANGLES, 0, HEIGHT_VERTS);
I have been suggested that it's because the size argument of glVertexAttribPointer() must be 1, 2, 3, or 4. I pass 5 with:
glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
but I get another error saying that I have too many vertices if these values are smaller (eg: #define VALS_PER_VERT_HEIGHT 3)
error: too many initializers for ‘float [15]’
I have attached the rest of my code for some context, I am very very new to OpenGL so I apologize if the code is messy.
#include <stdio.h>
// GLEW loads OpenGL extensions. Required for all OpenGL programs.
#include <GL/glew.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Utility code to load and compile GLSL shader programs
#include "shader.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#include "glm/glm.hpp"
#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
#define VALS_PER_VERT_HEIGHT 5//5
#define VALS_PER_COLOUR_HEIGHT 4
#define HEIGHT_VERTS 5 //height map vertices per line
using namespace std;
// Handle to our VAO generated in setShaderData method
//heightmap
unsigned int vertexVaoHandleHeight;
// Handle to our shader program
unsigned int programID;
/**
* Sets the shader uniforms and vertex data
* This happens ONCE only, before any frames are rendered
* #param id, Shader program object to use
* #returns 0 for success, error otherwise
*/
int setShaderData(const unsigned int &id)
{
float heightmapVerts[ HEIGHT_VERTS*VALS_PER_VERT_HEIGHT ] = {
//5
-0.9, -0.6, -0.4, -0.6, -0.9,
-0.2, 0.1, 0.3, 0.1, -0.3,
0, 0.4, 0.8, 0.4, 0,
-0.2, 0.1, 0.3, 0.1, -0.3,
0.5, -0.6, -0.4, -0.6, -0.9,
};
// Colours for each vertex; red, green, blue and alpha
// This data is indexed the same order as the vertex data, but reads 4 values
// Alpha will not be used directly in this example program
float heightColours[ HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT ] = {
0.8f, 0.7f, 0.5f, 1.0f,
0.3f, 0.7f, 0.1f, 1.0f,
0.8f, 0.2f, 0.5f, 1.0f,
};
// heightmap stuff ##################################################
// Generate storage on the GPU for our triangle and make it current.
// A VAO is a set of data buffers on the GPU
glGenVertexArrays(1, &vertexVaoHandleHeight);
glBindVertexArray(vertexVaoHandleHeight);
// Generate new buffers in our VAO
// A single data buffer store for generic, per-vertex attributes
unsigned int bufferHeight[2];
glGenBuffers(2, bufferHeight);
// Allocate GPU memory for our vertices and copy them over
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_VERT_HEIGHT, heightmapVerts, GL_STATIC_DRAW);
// Do the same for our vertex colours
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT, heightColours, GL_STATIC_DRAW);
// Now we tell OpenGL how to interpret the data we just gave it
// Tell OpenGL what shader variable it corresponds to
// Tell OpenGL how it's formatted (floating point, 3 values per vertex)
int vertLocHeight = glGetAttribLocation(id, "a_vertex");
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
glEnableVertexAttribArray(vertLocHeight);
glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
// Do the same for the vertex colours
int colourLocHeight = glGetAttribLocation(id, "a_colour");
glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
glEnableVertexAttribArray(colourLocHeight);
glVertexAttribPointer(colourLocHeight, VALS_PER_COLOUR_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
// heightmap stuff ##################################################
// An argument of zero un-binds all VAO's and stops us
// from accidentally changing the VAO state
glBindVertexArray(0);
// The same is true for buffers, so we un-bind it too
glBindBuffer(GL_ARRAY_BUFFER, 0);
return 0; // return success
}
/**
* Renders a frame of the state and shaders we have set up to the window
* Executed each time a frame is to be drawn.
*/
void render()
{
// Clear the previous pixels we have drawn to the colour buffer (display buffer)
// Called each frame so we don't draw over the top of everything previous
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
// HEIGHT MAP STUFF ###################################
// Make the VAO with our vertex data buffer current
glBindVertexArray(vertexVaoHandleHeight);
// Send command to GPU to draw the data in the current VAO as triangles
//CRASHES HERE
glDrawArrays(GL_TRIANGLES, 0, HEIGHT_VERTS);
glBindVertexArray(0); // Un-bind the VAO
// HEIGHT MAP STUFF ###################################
glutSwapBuffers(); // Swap the back buffer with the front buffer, showing what has been rendered
glFlush(); // Guarantees previous commands have been completed before continuing
}
You are messing things up.
1) With glVertexAttribPointer(), you setup vertex attributes - those are almost always vectors of some kind. For vertex position, if you need to draw scene in 2D, pass size = 2 (because each vertex has x and y coordinates), for 3D - pass 3 (x, y, z).
2) I think your interpretation of heightmap is also quite incorrect. You filled array only with height values (in 3D space, those are Y coordinates). But where are X and Z? You need to render vertices, so you need to pass all x, y and z coords, so OpenGL can know where each point should be rendered.
Your program crashes, because you send not enough data and OpenGL tries to read from memory, that doesn't belong to you.
I assume, that you want a heightmap, which is a 5x5 grid? Init data this way:
float heightmapVerts[25] =
{
//leave this as it is right now
};
vec3 vertices[5][5];
for(int z_num = 0; z_num < 5; ++z_num)
{
for(int x_num = 0; x_num < 5; ++x_num)
{
vertices[z_num][x_num].x = x_num * 0.5f;
vertices[z_num][x_num].z = z_num * 0.5f;
vertices[z_num][x_num].y = heightmapVerts[z_num * 5 + x_num];
}
}
Then you can call:
glVertexAttribPointer(vertLocHeight, 3, GL_FLOAT, GL_FALSE, 0, 0);
Update:
vec3 stands for 3-dimensional vector. I wrote it as pseudocode to
illustrate conception, but for the sake of simplicity, you may want to
use this great library: OpenGL Mathematics.
Update 2:
One more thing: color data is also set improperly. You probably want
color to be an RGB value, so every vertex needs additional 3 floats to
represent its color. Also, position and color should be place in
single VBO, there is no need for separating them.
I am not sure, if you got all basics required to do any simple
drawings. You may want to read these articles:
OpenGL Wiki
This nice tutorial
Lighthouse 3D
I have successfully created a VAO which produces a triangle which can then be rotated with the mouse (with help from shaders).
My problem comes when I try to draw something else using the standard 'glBegin()' and 'glEnd()' functions. It draws successfully, but now, when I try to rotate the triangle the new drawing also rotates.
I know the problem is somehow fixed using the glUseProgram() function, but I'm not entirely sure why or where it should be added.
Here is my code (I've added it all but the main area of focus should be the display() and init() functions:
#include <GL/glew/glew.h>
#include <GL/freeglut.h>
#include <CoreStructures\CoreStructures.h>
#include <iostream>
#include "texture_loader.h"
#include "shader_setup.h"
using namespace std;
using namespace CoreStructures;
float theta = 0.0f;
bool mDown = false;
int mouse_x, mouse_y;
GLuint myShaderProgram;
GLuint locT; // location of "T" uniform variable in myShaderProgram
GLuint locR; // location of "R" uniform variable in myShaderProgram
GLuint sunPosVBO, sunColourVBO, sunIndicesVBO, sunVAO;
// Packed vertex arrays for the star object
// 1) Position Array - Store vertices as (x,y) pairs
static GLfloat sunVertices [] = {
-0.1f, 0.7f,
0.1f, 0.7f,
0.0f, 0.55f
};
// 2) Colour Array - Store RGB values as unsigned bytes
static GLubyte sunColors [] = {
255, 0, 0, 255,
255, 255, 0, 255,
0, 255, 0, 255
};
// 4) Index Array - Store indices to star vertices - this determines the order the vertices are to be processed
static GLubyte sunVertexIndices [] = {0, 1, 2};
void setupSunVAO(void) {
glGenVertexArrays(1, &sunVAO);
glBindVertexArray(sunVAO);
// copy star vertex position data to VBO
glGenBuffers(1, &sunPosVBO);
glBindBuffer(GL_ARRAY_BUFFER, sunPosVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(sunVertices), sunVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
// copy star vertex colour data to VBO
glGenBuffers(1, &sunColourVBO);
glBindBuffer(GL_ARRAY_BUFFER, sunColourVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(sunColors), sunColors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const GLvoid*)0);
// enable position, colour buffer inputs
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// setup star vertex index array
glGenBuffers(1, &sunIndicesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sunIndicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sunVertexIndices), sunVertexIndices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void report_version(void) {
int majorVersion, minorVersion;
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
cout << "OpenGL version " << majorVersion << "." << minorVersion << "\n\n";
}
void init(void) {
// initialise glew library
GLenum err = glewInit();
// ensure glew was initialised successfully before proceeding
if (err==GLEW_OK)
cout << "GLEW initialised okay\n";
else
cout << "GLEW could not be initialised\n";
report_version();
glClearColor(0.0, 0.0, 0.0, 0.0);
//
// setup "sun" VBO and VAO object
//
setupSunVAO();
//
// load shader program
//
myShaderProgram = setupShaders(string("Resources\\Shaders\\basic_vertex_shader.txt"), string("Resources\\Shaders\\basic_fragment_shader.txt"));
// get the index / location of the uniform variables "T" and "R" in shader program "myShaderProgram"
locT = glGetUniformLocation(myShaderProgram, "T");
locR = glGetUniformLocation(myShaderProgram, "R");
// "plug-in" shader into GPU pipeline
glUseProgram(myShaderProgram); // we're in the driving seat!!!!! Our shaders now intercept and process our vertices as part of the GPU rendering pipeline (as shown in the lecture notes)
}
// Example rendering functions - draw objects in local, or modelling coordinates
void drawSun(void) {
glBindVertexArray(sunVAO);
glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_BYTE, (GLvoid*)0);
}
void drawShape()
{
glColor3f(0.0f, 0.6f, 0.2f);
glBegin(GL_POLYGON);
glVertex2f(-1.0f, -1.0f); // Left
glVertex2f(-1.0f, -0.1f);
glVertex2f(-0.9f, -0.05f);
glVertex2f(-0.55f, -0.045f);
glVertex2f(-0.49f, -0.06f);
glVertex2f(-0.4f, -0.055f);
glVertex2f(-0.2f, -0.052f);
glVertex2f(0.0f, -0.02f); // Middle
glVertex2f(0.3f, -0.085f);
glVertex2f(0.5f, -0.08f);
glVertex2f(0.8f, -0.088f);
glVertex2f(1.0f, -0.1f);
glVertex2f(1.0f, -1.0f); // Right
glEnd();
}
//
//
void drawScene()
{
drawSun();
drawShape();
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup translation matrix and store in T. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);
// Setup rotation matrix and store in R. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
// Draw the scene (the above transformations will be applied to each vertex in the vertex shader)
drawScene();
glutSwapBuffers();
}
void mouseButtonDown(int button_id, int state, int x, int y) {
if (button_id==GLUT_LEFT_BUTTON) {
if (state==GLUT_DOWN) {
mouse_x = x;
mouse_y = y;
mDown = true;
} else if (state == GLUT_UP) {
mDown = false;
}
}
}
void mouseMove(int x, int y) {
if (mDown) {
int dx = x - mouse_x;
int dy = y - mouse_y;
float delta_theta = (float)dy * (3.142f * 0.01f);
theta += delta_theta;
mouse_x = x;
mouse_y = y;
glutPostRedisplay();
}
}
void keyDown(unsigned char key, int x, int y) {
if (key=='r') {
theta = 0.0f;
glutPostRedisplay();
}
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
initCOM();
glutInitContextVersion(3, 3);
glutInitContextProfile (GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow("Combining Transforms");
glutDisplayFunc(display);
glutKeyboardFunc(keyDown);
glutMouseFunc(mouseButtonDown);
glutMotionFunc(mouseMove);
init();
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutMainLoop();
shutdownCOM();
return 0;
}
EDIT
I have an array of x,y vertices and am trying to draw them alongside the above code. For some reason this seems to take vertex data from the sunVAO.
Is there some kind of cache that needs to be cleared? I've searched google and I can't seem to find anyone else who has conflicting VAO and vertex arrays.
(Also, I have checked my code and the vertex data supplied in the array of vertices is correct, they're just not displayed correctly.)
Code:
static GLfloat bottomMarkerVertices[] = {
-0.045f, -0.75f,
0.045f, -0.75f,
-0.07f, -1.0f,
0.07f, -1.0f
};
glVertexPointer(2, GL_FLOAT, 0, bottomMarkerVertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
note: vertex arrays have been enabled.
Assuming you're defining your coordinates in normalized device space (suggested by the apparent absence of a projection matrix), the rendering loop needs to look a little like this:
void drawScene()
{
//update shader parameters for the sun shader if necessary
drawSun();
glUseProgram(0);
// at this point, the PROJECTION and MODELVIEW matrices are both the identity
// so the shape is expected to be in NDCs and is not to be transformed
// at all
drawShape();
glUseProgram(progForSun);
}
Note that I don't advise to mix legacy and modern OpenGL like that. The results of vertex processing triggered by drawShape() are only defined because you're using a compatibility profile context.
The two elements of your scene move together because they are both using the same transformation matrices, specificed by these lines:
// Setup translation matrix and store in T. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 T = GUMatrix4::translationMatrix(0.01f, 0.01f, 0.0f);
glUniformMatrix4fv(locT, 1, GL_FALSE, (GLfloat*)&T);
// Setup rotation matrix and store in R. Pass this over the the shader with the function glUniformMatrix4fv
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, theta);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
If you want drawShape() not to move with the mouse, you need to reset locR with a fixed theta value before you call it.
drawSun();
GUMatrix4 R = GUMatrix4::rotationMatrix(0.0f, 0.0f, 0.0f);
glUniformMatrix4fv(locR, 1, GL_FALSE, (GLfloat*)&R);
drawShape();