I am drawing a 3D cube with texture and i get sth like this. I dont exactly know what is wrong ;/
http://i.stack.imgur.com/081nl.png
Vectors for texturecord
vec2(0.0f, 0.0f),
vec2(1.0f, 0.0f),
vec2(1.0f, 1.0f),
vec2(0.0f, 1.0f),
....
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
....
glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
....
color = texture(myTextureSampler,UV); //SHADER CODE
To load first example i used:
SDL_Surface* textures;
textures = SDL_LoadBMP(filename);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, textures->w, textures->h, 0, GL_RGB, GL_UNSIGNED_BYTE, textures->pixels);
To second pics i used :
int width, height;
GLubyte * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
width = 128;
height = 128;
data = (GLubyte *)malloc(width * height * 3);
//int size = fseek(file,);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, data);
The both doesnt work correct;// any ideas?
Complete program:
main.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <GL\glew.h> // UP
#include <GL\glut.h>
#include <GLFW\glfw3.h>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtx\transform.hpp>
#include <SDL.h>
using namespace glm;
GLuint LoadTexture(const char * filename)
{
int width, height;
GLubyte * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
width = 128;
height = 128;
data = (GLubyte *)malloc(width * height * 3);
//int size = fseek(file,);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
//free(data);
return texture;
/**
SDL_Surface* textures;
textures = SDL_LoadBMP(filename);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, textures->w, textures->h, 0, GL_RGB, GL_UNSIGNED_BYTE, textures->pixels);
return texture;
**/
}
std::string LoadFileToString(const char* filepath){
std::string fileData = "";
std::ifstream stream(filepath, std::ios::in);
if (stream.is_open()){
std::string line = "";
while (getline(stream, line)){
fileData += "\n" + line;
}
stream.close();
}
return fileData;
}
GLuint LoadShaders(const char*VertShaderPath, const char* fragShaderPath){
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
std::string vertShaderSource = LoadFileToString(VertShaderPath);
std::string fragShaderSource = LoadFileToString(fragShaderPath);
const char* rawVertShaderSource = vertShaderSource.c_str();
const char* rawfragShaderSource = fragShaderSource.c_str();
glShaderSource(vertShader, 1, &rawVertShaderSource, NULL);
glShaderSource(fragShader, 1, &rawfragShaderSource, NULL);
glCompileShader(vertShader);
glCompileShader(fragShader);
GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
return program;
}
const float movementspeed = 0.01f;
class Camera{
vec3 position;
vec3 viewDirection;
const vec3 UP;
vec2 oldmouseposition;
public:
Camera();
mat4 getWorldToViewMatrix() const;
void mouseUpdate(const vec2 &newMousePosition);
void moveForward();
void moveBackWard();
void left();
void right();
void up();
void down();
};
Camera::Camera() :viewDirection(0.0f, 0.0f, -1.0f), UP(0.0f, 1.0f, 0.0f){}
void Camera::mouseUpdate(const vec2 &newMousePosition){
glm::vec2 mouseDelta = newMousePosition - oldmouseposition;
if (glm::length(mouseDelta) >10.0f)
{
oldmouseposition = newMousePosition;
return;
}
viewDirection = glm::mat3(glm::rotate(-mouseDelta.x*0.5f, UP)) * viewDirection;
oldmouseposition = newMousePosition;
}
void Camera::moveForward(){
position -= movementspeed *viewDirection;
}
void Camera::moveBackWard(){
position += movementspeed *viewDirection;
}
void Camera::left(){
glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
position += movementspeed *strafeDirection;
}
void Camera::right(){
glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
position += -movementspeed *strafeDirection;
}
void Camera::up(){
position += movementspeed *UP;
}
void Camera::down(){
position += -movementspeed *UP;
}
mat4 Camera::getWorldToViewMatrix() const {
return lookAt(position, position - viewDirection, UP);
}
int main(int argc, char ** argv)
{
if (!glfwInit())
exit(EXIT_FAILURE);
GLFWwindow* window;
window = glfwCreateWindow(640, 480, "My 3D World", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glewExperimental = true;
if (glewInit() != GLEW_OK){
glfwTerminate();
exit(EXIT_FAILURE);
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
GLuint program = LoadShaders("vertex.wss", "fragment.fss"); // shadersprogram
struct Vertex{
glm::vec3 position;
glm::vec3 color;
glm::vec2 texture;
glm::vec3 normal;
};
Vertex verts[] = {
vec3(-1.0f, +1.0f, +1.0f), // 0
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 1
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 2
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 3
vec3(0.0f, 0.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 4
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 5
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), //
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 7
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 8
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 9
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 10
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), // 11
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(-1.0f, +1.0f, +1.0f), // 12
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 13
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 14
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 15
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 16
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, +1.0f), // 17
vec3(1.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 18
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 19
vec3(1.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), // 20
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 21
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 22
vec3(0.0f, 1.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 23
vec3(1.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f) //normal
};
GLushort indices[] = {
0, 1, 2, 0, 2, 3, // Top
4, 5, 6, 4, 6, 7, // Front
8, 9, 10, 8, 10, 11, // Right
12, 13, 14, 12, 14, 15, // Left
16, 17, 18, 16, 18, 19, // Back
20, 22, 21, 20, 23, 22 // Bottom
};
////////VAO niepotrzebne
////////VBO
GLuint vboID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
GLuint indexbuff;
glGenBuffers(1, &indexbuff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
//////
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, LoadTexture("block"));
Camera camera;
while (!glfwWindowShouldClose(window))
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(program);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
camera.moveForward();
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
camera.moveBackWard();
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
camera.left();
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
camera.right();
}
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS){
camera.up();
}
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS){
camera.down();
}
if (xpos > 0 && xpos < 640 && ypos>0 && ypos < 400){
camera.mouseUpdate(vec2(float(xpos / 50), float(ypos / 50)));
std::cout << "pos x: " << xpos << "pos y: " << ypos << std::endl;
}
// textures
glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
//AMBIENT LIGHT
GLint ambientlightlocation = glGetUniformLocation(program, "ambientLight");
vec3 ambientLight(0.3f, 0.3f, 0.3f);
glUniform3fv(ambientlightlocation, 1, &ambientLight[0]);
//Light
GLint lightlocation = glGetUniformLocation(program, "lightPosition");
vec3 lightposition(1.0f, 1.0f, -3.75f);
glUniform3fv(lightlocation, 1, &lightposition[0]);
GLint fullTransformMatrixUniformLocation = glGetUniformLocation(program, "fullTransformMatrix");
mat4 fullTransformMatrix;
mat4 projectionMatrix = perspective(90.0f, (480.0f / 640.0f), 0.1f, 5.0f);
mat4 worldToProjectionMatrix = projectionMatrix* camera.getWorldToViewMatrix();
//CUBE 1 tak sie robi gdyby sie roznily
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
mat4 cube1WorldMatrix = translate(vec3(1.0f, 0.0f, -3.75f)) * rotate(0.0f, vec3(0.0f, 1.0f, 1.0f));
fullTransformMatrix = worldToProjectionMatrix *cube1WorldMatrix;
glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
// CUBE 2 gdyby byly rozne
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
mat4 cube2WorldMatrix = translate(vec3(-3.0f, 0.0f, -3.75f)) * rotate(126.0f, vec3(1.0f, 0.0f, 0.0f));
fullTransformMatrix = worldToProjectionMatrix *cube2WorldMatrix;
glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
fragment.fss:
#version 330 core
out vec4 color;
in vec3 theColor;
in vec2 UV;
uniform sampler2D myTextureSampler;
void main()
{
color = texture(myTextureSampler,UV);
//texture(myTextureSampler,UV);
// * vec4(theColor,1.0);
}
vertex.wss:
#version 330 core
layout(location=0) in vec3 in_pos;
layout(location=1) in vec3 vertexColor;
layout(location=2) in vec2 vertexUV;
layout(location=3) in vec3 normal;
uniform mat4 fullTransformMatrix;
uniform vec3 ambientLight;
uniform vec3 lightPosition;
out vec3 theColor;
out vec2 UV;
void main()
{
vec4 v = vec4(in_pos, 1.0);
gl_Position = fullTransformMatrix* v;
vec3 lightVector = normalize(lightPosition-normal);
float brightness = dot(lightVector,normal);
theColor = vertexColor * vec3( brightness, brightness, brightness);// * ambientLight;
UV = vertexUV;
}
If you want to load compressed images you'll need a proper decoder.
Your LoadTexture() function was assuming everything passed in
is an uncompressed, tightly-packed blob of RGB triplets, which is...not a good assumption :)
Here's an example using stb_image and a screenshot PNG:
GLuint LoadTexture(const char * filename)
{
int width = 0, height = 0, n = 0;
unsigned char* data = stbi_load
(
filename,
&width,
&height,
&n,
3
);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free( data );
return texture;
}
All together:
#include <iostream>
#include <cstdarg>
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#define GLM_FORCE_RADIANS
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtx\transform.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace glm;
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
330 core,
layout(location=0) in vec3 in_pos;
layout(location=1) in vec3 vertexColor;
layout(location=2) in vec2 vertexUV;
layout(location=3) in vec3 normal;
uniform mat4 fullTransformMatrix;
uniform vec3 ambientLight;
uniform vec3 lightPosition;
out vec3 theColor;
out vec2 UV;
void main()
{
vec4 v = vec4(in_pos, 1.0);
gl_Position = fullTransformMatrix* v;
vec3 lightVector = normalize(lightPosition-normal);
float brightness = dot(lightVector,normal);
theColor = vertexColor * vec3( brightness, brightness, brightness);// * ambientLight;
UV = vertexUV;
}
);
const char* frag = GLSL
(
330 core,
out vec4 color;
in vec3 theColor;
in vec2 UV;
uniform sampler2D mySampler;
void main()
{
color = texture(mySampler,UV);
}
);
GLuint LoadTexture(const char * filename)
{
int width = 0, height = 0, n = 0;
unsigned char* data = stbi_load
(
filename,
&width,
&height,
&n,
3
);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free( data );
return texture;
}
const float movementspeed = 0.01f;
class Camera{
vec3 position;
vec3 viewDirection;
const vec3 UP;
vec2 oldmouseposition;
public:
Camera();
mat4 getWorldToViewMatrix() const;
void mouseUpdate(const vec2 &newMousePosition);
void moveForward();
void moveBackWard();
void left();
void right();
void up();
void down();
};
Camera::Camera() :viewDirection(0.0f, 0.0f, -1.0f), UP(0.0f, 1.0f, 0.0f){}
void Camera::mouseUpdate(const vec2 &newMousePosition){
glm::vec2 mouseDelta = newMousePosition - oldmouseposition;
if (glm::length(mouseDelta) >10.0f)
{
oldmouseposition = newMousePosition;
return;
}
viewDirection = glm::mat3(glm::rotate(-mouseDelta.x*0.5f, UP)) * viewDirection;
oldmouseposition = newMousePosition;
}
void Camera::moveForward(){
position -= movementspeed *viewDirection;
}
void Camera::moveBackWard(){
position += movementspeed *viewDirection;
}
void Camera::left(){
glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
position += movementspeed *strafeDirection;
}
void Camera::right(){
glm::vec3 strafeDirection = glm::cross(viewDirection, UP);
position += -movementspeed *strafeDirection;
}
void Camera::up(){
position += movementspeed *UP;
}
void Camera::down(){
position += -movementspeed *UP;
}
mat4 Camera::getWorldToViewMatrix() const {
return lookAt(position, position - viewDirection, UP);
}
int main(int argc, char ** argv)
{
if (!glfwInit())
exit(EXIT_FAILURE);
GLFWwindow* window;
window = glfwCreateWindow(640, 480, "My 3D World", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glewExperimental = true;
if (glewInit() != GLEW_OK){
glfwTerminate();
exit(EXIT_FAILURE);
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
GLuint program = Program::Load
(
vert, GL_VERTEX_SHADER,
frag, GL_FRAGMENT_SHADER,
NULL
);
struct Vertex{
glm::vec3 position;
glm::vec3 color;
glm::vec2 texture;
glm::vec3 normal;
};
Vertex verts[] = {
vec3(-1.0f, +1.0f, +1.0f), // 0
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 1
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 2
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 3
vec3(0.0f, 0.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 4
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 5
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), //
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 7
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, -1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, -1.0f), // 8
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 9
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 10
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), // 11
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 0.0f, -1.0f), //normal
vec3(-1.0f, +1.0f, +1.0f), // 12
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, -1.0f), // 13
vec3(1.0f, 0.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 14
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 15
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, +1.0f, +1.0f), // 16
vec3(0.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, +1.0f, +1.0f), // 17
vec3(1.0f, 0.0f, 1.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 18
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 19
vec3(1.0f, 0.0f, 1.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, -1.0f), // 20
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, -1.0f), // 21
vec3(0.0f, 1.0f, 0.0f), // Colour
vec2(1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(-1.0f, -1.0f, +1.0f), // 22
vec3(0.0f, 1.0f, 1.0f), // Colour
vec2(1.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f), //normal
vec3(+1.0f, -1.0f, +1.0f), // 23
vec3(1.0f, 1.0f, 0.0f), // Colour
vec2(0.0f, 1.0f),
vec3(0.0f, 1.0f, 0.0f) //normal
};
GLushort indices[] = {
0, 1, 2, 0, 2, 3, // Top
4, 5, 6, 4, 6, 7, // Front
8, 9, 10, 8, 10, 11, // Right
12, 13, 14, 12, 14, 15, // Left
16, 17, 18, 16, 18, 19, // Back
20, 22, 21, 20, 23, 22 // Bottom
};
////////VAO niepotrzebne
////////VBO
GLuint vboID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
GLuint indexbuff;
glGenBuffers(1, &indexbuff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
//////
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, LoadTexture("TADdR.png"));
Camera camera;
while (!glfwWindowShouldClose(window))
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(program);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
camera.moveForward();
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
camera.moveBackWard();
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
camera.left();
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
camera.right();
}
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS){
camera.up();
}
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS){
camera.down();
}
if (xpos > 0 && xpos < 640 && ypos>0 && ypos < 400){
camera.mouseUpdate(vec2(float(xpos / 50), float(ypos / 50)));
std::cout << "pos x: " << xpos << "pos y: " << ypos << std::endl;
}
// textures
glUniform1i(glGetUniformLocation(program, "mySampler"), 0);
//AMBIENT LIGHT
GLint ambientlightlocation = glGetUniformLocation(program, "ambientLight");
vec3 ambientLight(0.3f, 0.3f, 0.3f);
glUniform3fv(ambientlightlocation, 1, &ambientLight[0]);
//Light
GLint lightlocation = glGetUniformLocation(program, "lightPosition");
vec3 lightposition(1.0f, 1.0f, -3.75f);
glUniform3fv(lightlocation, 1, &lightposition[0]);
GLint fullTransformMatrixUniformLocation = glGetUniformLocation(program, "fullTransformMatrix");
mat4 fullTransformMatrix;
mat4 projectionMatrix = perspective( glm::radians( 90.0f ), (480.0f / 640.0f), 0.1f, 5.0f);
mat4 worldToProjectionMatrix = projectionMatrix* camera.getWorldToViewMatrix();
//CUBE 1 tak sie robi gdyby sie roznily
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
mat4 cube1WorldMatrix = translate(vec3(1.0f, 0.0f, -3.75f)) * rotate(0.0f, vec3(0.0f, 1.0f, 1.0f));
fullTransformMatrix = worldToProjectionMatrix *cube1WorldMatrix;
glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
// CUBE 2 gdyby byly rozne
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 6));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, (char*)(sizeof(float) * 9));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuff);
mat4 cube2WorldMatrix = translate(vec3(-3.0f, 0.0f, -3.75f)) * rotate(126.0f, vec3(1.0f, 0.0f, 0.0f));
fullTransformMatrix = worldToProjectionMatrix *cube2WorldMatrix;
glUniformMatrix4fv(fullTransformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Related
I've spent 2 weeks trying to get OpenGL to draw a cube in 3D, but no matter what I do, it never actually drew a cube. If I enable the depth test with glEnable(DEPTH_TEST), it simply does not render anything. If I comment out that function, it renders all the vertices as if the z-values were all 0. I'm completely stuck and have no idea what i've done wrong.
Here's my main file: https://pastebin.com/D8cEcJ4g
#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include "Dependencies\soil\SOIL.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include "ShaderLoader.h";
#include "Camera.h"
#define BUTTON_UP 0
#define BUTTON_DOWN 1
GLuint program;
GLuint vao, vbo, ebo;
GLuint texture, texture2;
unsigned char keyState[255];
glm::vec3 vPosTrans = glm::vec3(-0.50f, -0.50f, 0.0f);//source
glm::vec3 vPosInit = vPosTrans;
glm::vec3 vPosDest = glm::vec3(0.50f, 0.50f, 0.0f);//destination
glm::vec3 vCurrentPos = vPosTrans;
bool Dest1or2 = true;
const GLfloat WIDTH = 800.0f, HEIGHT = 600.0f;
Camera* camera;
void init(){
camera = new Camera(180.0f, WIDTH, HEIGHT, 0.0f, 100.0f);
ShaderLoader shaderLoader;
program = shaderLoader.CreateProgram("CoordSystem_Texture_QUAD.vs", "CoordSystem_Texture_QUAD.fs");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
//position //color //texture coord //Normals
-1.01f, -1.01f, -1.01f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, -0.0f, 0.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 0.0f, -0.0f, 1.0f, 0.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// Fill in the back face vertex data.
-1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.01f, -1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the top face vertex data.
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the bottom face vertex data.
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the left face vertex data.
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, -1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the right face vertex data.
1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint indices[] = {
// front
0, 1, 2,
0, 2, 3,
// top
4, 5, 6,
4, 6, 7,
// back
8, 9, 10,
8, 10, 11,
// bottom
12, 13, 14,
12, 14, 15,
// left
16, 17, 18,
16, 18, 19,
// right
20, 21, 22,
20, 22, 23,
};
//** VAO **
// Generate vertex arrow object
glGenVertexArrays(1, &vao);
// Bind the Vertex Array Object to openGl context
glBindVertexArray(vao);//otherwise glVertexAttribPointer
//** VBO **
// Then bind and set vertex buffer(s).
// First paramter is how many buffers we have to create
glGenBuffers(1, &vbo);
// bind VBO to binding point, here it is GL_ARRAY_BUFFER
// there are other binding points
glBindBuffer(GL_ARRAY_BUFFER, vbo);//bind to context
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices),// GPU need to know how much memory needs to be allocated
vertices,//copy data to GPU
GL_STATIC_DRAW);// How to use the buffer - buffer is created and modified once
//** EBO **
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices),
indices,
GL_STATIC_DRAW);
// ** Attributes **
//** Vertex Attribute **
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//** Color Attribute **
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//** TexCoord attribute **
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// It's always a good thing to unbind any buffer/array to prevent strange bugs
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//** Load and bind texture 1
//--------------------------
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
int width, height;
unsigned char* image = SOIL_load_image("wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// ** Load and Bind Texture 2
//---------------------------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
unsigned char* image2 = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image2);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image2);
glBindTexture(GL_TEXTURE_2D, 0);
// Set texture wrapping to GL_REPEAT (usually basic wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw our first triangle
glUseProgram(program);
//bind
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "Texture"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(program, "Texture2"), 1);
glBindVertexArray(vao);
// Draw Elements intead of vertex array
glDrawArrays(GL_QUADS, 0, 24);
//glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glutSwapBuffers();
}
void update(){
GLfloat cameraSpeed = 0.05f;
camera->setCameraSpeed(cameraSpeed);
//currentTime uniform
GLfloat currentTime = glutGet(GLUT_ELAPSED_TIME);
currentTime = currentTime / 1000;
GLint currentTimeLocation = glGetUniformLocation(program, "currentTime");
glUniform1f(currentTimeLocation, currentTime);
//transforms
glm::mat4 transform = glm::mat4(1.0f);
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
glm::mat4 model = glm::mat4(1.0);
if (keyState[(unsigned char)'w'] == BUTTON_DOWN) {
camera->moveForward();
std::cout << "e";
}
if (keyState[(unsigned char)'s'] == BUTTON_DOWN) {
camera->moveBack();
std::cout << "A";
}
camera->Update();
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
glm::mat4 projection = camera->getProjectionMatrix();
glm::mat4 view = glm::lookAt(camera->getCameraPos(), camera->getCameraPos() + camera->getCameraFront(), camera->getCameraUp());
//glm::mat4 view = glm::lookAt(glm::vec3(1, 1, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1));
GLfloat radius = 3.5f;
GLfloat camX = sin(currentTime) * radius;
GLfloat camZ = cos(currentTime) * radius;
//glm::mat4 view = glm::lookAt(
// glm::vec3(camX, 0.0, camZ),
// glm::vec3(0.0, 0.0, 0.0),
// glm::vec3(0.0, 1.0, 0.0));
transform = glm::scale(transform, vScaleVec);
glm::vec3(0.65f, 0.65f, 0.65f);
//transform = glm::rotate(transform, 90.0f, glm::vec3(0.0, 0.0, 1.0));
if (vCurrentPos == vPosDest && Dest1or2 == true )
{
Dest1or2 = false;
}
else if (vCurrentPos == vPosTrans && Dest1or2 == false)
{
Dest1or2 = true;
}
if(Dest1or2)
vCurrentPos = glm::mix(vCurrentPos, vPosDest, currentTime * 0.01f);
else
vCurrentPos = glm::mix(vCurrentPos, vPosTrans, currentTime*0.01f);
//transform = glm::translate(transform, vCurrentPos);
//transform = glm::translate(transform, glm::vec3(-0.51f, -0.51f, 0.0f));
//transform = glm::rotate(transform, ((GLfloat)currentTime / 100) * 90.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// RTS
GLuint transformLoc = glGetUniformLocation(program, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
GLint modelLoc = glGetUniformLocation(program, "model");
GLint viewLoc = glGetUniformLocation(program, "view");
GLint projLoc = glGetUniformLocation(program, "projection");
// Pass them to the shaders
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(camera->getViewMatrix()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(camera->getProjectionMatrix()));
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
keyState[key] = BUTTON_DOWN;
//printf("key pressed: %d \n", key);
}
void keyboard_up(unsigned char key, int x, int y) {
keyState[key] = BUTTON_UP;
}
int main(int argc, char **argv){
// init glut
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(300, 200);
glutInitWindowSize(800, 600);
glutCreateWindow("QUAD EBO");
//init GLEW
glewInit();
init();
//clear
glClearColor(1.0, 0.0, 0.0, 1.0);//clear red
// register callbacks
glutDisplayFunc(render);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboard_up);
glutIdleFunc(update);
glutMainLoop();
return 0;
}
RAW Paste Data
#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include "Dependencies\soil\SOIL.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include "ShaderLoader.h";
#include "Camera.h"
#define BUTTON_UP 0
#define BUTTON_DOWN 1
GLuint program;
GLuint vao, vbo, ebo;
GLuint texture, texture2;
unsigned char keyState[255];
glm::vec3 vPosTrans = glm::vec3(-0.50f, -0.50f, 0.0f);//source
glm::vec3 vPosInit = vPosTrans;
glm::vec3 vPosDest = glm::vec3(0.50f, 0.50f, 0.0f);//destination
glm::vec3 vCurrentPos = vPosTrans;
bool Dest1or2 = true;
const GLfloat WIDTH = 800.0f, HEIGHT = 600.0f;
Camera* camera;
void init(){
camera = new Camera(180.0f, WIDTH, HEIGHT, 0.0f, 100.0f);
ShaderLoader shaderLoader;
program = shaderLoader.CreateProgram("CoordSystem_Texture_QUAD.vs", "CoordSystem_Texture_QUAD.fs");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
//position //color //texture coord //Normals
-1.01f, -1.01f, -1.01f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, -0.0f, 0.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 0.0f, -0.0f, 1.0f, 0.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// Fill in the back face vertex data.
-1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.01f, -1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the top face vertex data.
-1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
1.01f, 1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the bottom face vertex data.
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.01f, -1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// Fill in the left face vertex data.
-1.01f, -1.01f, 1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-1.01f, 1.01f, -1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// Fill in the right face vertex data.
1.01f, -1.01f, -1.01f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.01f, 1.01f, -1.01f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.01f, 1.01f, 1.01f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.01f, -1.01f, 1.01f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint indices[] = {
// front
0, 1, 2,
0, 2, 3,
// top
4, 5, 6,
4, 6, 7,
// back
8, 9, 10,
8, 10, 11,
// bottom
12, 13, 14,
12, 14, 15,
// left
16, 17, 18,
16, 18, 19,
// right
20, 21, 22,
20, 22, 23,
};
//** VAO **
// Generate vertex arrow object
glGenVertexArrays(1, &vao);
// Bind the Vertex Array Object to openGl context
glBindVertexArray(vao);//otherwise glVertexAttribPointer
//** VBO **
// Then bind and set vertex buffer(s).
// First paramter is how many buffers we have to create
glGenBuffers(1, &vbo);
// bind VBO to binding point, here it is GL_ARRAY_BUFFER
// there are other binding points
glBindBuffer(GL_ARRAY_BUFFER, vbo);//bind to context
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices),// GPU need to know how much memory needs to be allocated
vertices,//copy data to GPU
GL_STATIC_DRAW);// How to use the buffer - buffer is created and modified once
//** EBO **
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices),
indices,
GL_STATIC_DRAW);
// ** Attributes **
//** Vertex Attribute **
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//** Color Attribute **
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//** TexCoord attribute **
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// It's always a good thing to unbind any buffer/array to prevent strange bugs
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//** Load and bind texture 1
//--------------------------
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
int width, height;
unsigned char* image = SOIL_load_image("wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// ** Load and Bind Texture 2
//---------------------------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
//** loadImage and create texture
// Load image, create texture and generate mipmaps
unsigned char* image2 = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image2);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image2);
glBindTexture(GL_TEXTURE_2D, 0);
// Set texture wrapping to GL_REPEAT (usually basic wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw our first triangle
glUseProgram(program);
//bind
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "Texture"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(program, "Texture2"), 1);
glBindVertexArray(vao);
// Draw Elements intead of vertex array
glDrawArrays(GL_QUADS, 0, 24);
//glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glutSwapBuffers();
}
void update(){
GLfloat cameraSpeed = 0.05f;
camera->setCameraSpeed(cameraSpeed);
//currentTime uniform
GLfloat currentTime = glutGet(GLUT_ELAPSED_TIME);
currentTime = currentTime / 1000;
GLint currentTimeLocation = glGetUniformLocation(program, "currentTime");
glUniform1f(currentTimeLocation, currentTime);
//transforms
glm::mat4 transform = glm::mat4(1.0f);
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
glm::mat4 model = glm::mat4(1.0);
if (keyState[(unsigned char)'w'] == BUTTON_DOWN) {
camera->moveForward();
std::cout << "e";
}
if (keyState[(unsigned char)'s'] == BUTTON_DOWN) {
camera->moveBack();
std::cout << "A";
}
camera->Update();
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
glm::mat4 projection = camera->getProjectionMatrix();
glm::mat4 view = glm::lookAt(camera->getCameraPos(), camera->getCameraPos() + camera->getCameraFront(), camera->getCameraUp());
//glm::mat4 view = glm::lookAt(glm::vec3(1, 1, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1));
GLfloat radius = 3.5f;
GLfloat camX = sin(currentTime) * radius;
GLfloat camZ = cos(currentTime) * radius;
//glm::mat4 view = glm::lookAt(
// glm::vec3(camX, 0.0, camZ),
// glm::vec3(0.0, 0.0, 0.0),
// glm::vec3(0.0, 1.0, 0.0));
transform = glm::scale(transform, vScaleVec);
glm::vec3(0.65f, 0.65f, 0.65f);
//transform = glm::rotate(transform, 90.0f, glm::vec3(0.0, 0.0, 1.0));
if (vCurrentPos == vPosDest && Dest1or2 == true )
{
Dest1or2 = false;
}
else if (vCurrentPos == vPosTrans && Dest1or2 == false)
{
Dest1or2 = true;
}
if(Dest1or2)
vCurrentPos = glm::mix(vCurrentPos, vPosDest, currentTime * 0.01f);
else
vCurrentPos = glm::mix(vCurrentPos, vPosTrans, currentTime*0.01f);
//transform = glm::translate(transform, vCurrentPos);
//transform = glm::translate(transform, glm::vec3(-0.51f, -0.51f, 0.0f));
//transform = glm::rotate(transform, ((GLfloat)currentTime / 100) * 90.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// RTS
GLuint transformLoc = glGetUniformLocation(program, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
GLint modelLoc = glGetUniformLocation(program, "model");
GLint viewLoc = glGetUniformLocation(program, "view");
GLint projLoc = glGetUniformLocation(program, "projection");
// Pass them to the shaders
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(camera->getViewMatrix()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(camera->getProjectionMatrix()));
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
keyState[key] = BUTTON_DOWN;
//printf("key pressed: %d \n", key);
}
void keyboard_up(unsigned char key, int x, int y) {
keyState[key] = BUTTON_UP;
}
int main(int argc, char **argv){
// init glut
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(300, 200);
glutInitWindowSize(800, 600);
glutCreateWindow("QUAD EBO");
//init GLEW
glewInit();
init();
//clear
glClearColor(1.0, 0.0, 0.0, 1.0);//clear red
// register callbacks
glutDisplayFunc(render);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboard_up);
glutIdleFunc(update);
glutMainLoop();
return 0;
}
Fragment Shader:
#version 430 core
in vec3 outColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D Texture;
uniform sampler2D Texture2;
uniform float currentTime;
void main()
{
//vec3 colorTemp = outColor * abs(sin(currentTime));
//color = vec4(colorTemp, 1.0f) ;
//color = texture(ourTexture, TexCoord) * vec4(outColor, 1.0f) * abs(sin(currentTime)) ;
color = mix(texture(Texture, TexCoord), texture(Texture2, TexCoord), 0.2) * vec4(outColor, 1.0f) * abs(sin(currentTime));
}
Vertex shader:
#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 outColor;
out vec2 TexCoord;
uniform mat4 transform;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(void)
{
gl_Position = projection * view * model * transform * vec4(position, 1.0);
outColor = color;
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}
If I comment out that function, it renders all the vertices as if the z-values were all 0
Well, that's because ... they are:
glm::vec3 vScaleVec = glm::vec3(0.51f, 0.51f, 0.0f);
[...]
transform = glm::scale(transform, vScaleVec);
[...]
gl_Position = projection * view * model * transform * vec4(position, 1.0);
You scale with z=0, which means you move all vertices into the z = 0 plane. So it is already flat after your first transformation step (which also means transform is a singular matrix with the third row and column being all zeros). The additional transform steps you have commented out in the code, as well as all the other matrices applied in the shader, won't change any of that, the object is still a flat plane, no matter what other matrices you pre- or post-multiply to it, they just move that plane around.
I don't know which amount of scaling you want, but scaling by 0 is almost never a good idea, and 1 is the neutral element for scaling operations.
Also, why do you have model and transform as separate matrices in the shader? In 3d computer graphics, the model matrix typically contains all the transformations required for mapping the object from it's own local model space to the world space. Even if you need to track separate parts of the transformation internally, you typically don't need these during actual rendering on the gpu, and should multiply all of these together on the CPU, and just send the accumulated transformation as the model matrix to the shader.
I have this OpenGL program in C++ which is a moving circle, vubes in the background and a line which can move up or down is you press the W or the S button. When the line is in the middle of the screen the cubes which are below the line should have green color, and for the cubes above the line the color should be red.
When the line is moved up the color of the cubes should change, so when the line is in the top of the scrren every cube needs to be red.
In my code when I move the Line up it changes his color when it needs to be but the cubes has the color from the beginning of the run to the end, no matter where I move the line.
Attaching the code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "glm/glm.hpp"
#include <array>
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <math.h>
#define COORDMIN -0.7
#define COORDMAX 0.7
#define PI 3.14159265359
using namespace std;
GLuint VBO;
GLuint VAO;
GLuint VBO1;
GLuint VAO1;
GLuint VBO2;
GLuint VAO2;
static int WIN_WIDTH = 600;
static int WIN_HEIGHT = 600;
float x = 0.0f;
float y = 0.0f;
float inc = 0.01f;
float inc1 = 0.01f;
bool up = true;
bool down = false;
float fel = 1.0f;
float le = -1.0f;
bool xDir = true;
bool yDir = false;
bool go = true;
GLfloat p;
std::vector<glm::vec3> linePoints;
glm::vec3 vertices[] = {
glm::vec3(-0.9f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor1
glm::vec3(-0.7f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, 0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor1
glm::vec3(-0.9f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 2
glm::vec3(-0.7f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, 0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 2
glm::vec3(-0.9f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 3
glm::vec3(-0.7f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, 0.5, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, 0.5, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, 0.5, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 3
glm::vec3(-0.9f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 4
glm::vec3(-0.7f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, 0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 4
glm::vec3(-0.9f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 5
glm::vec3(-0.7f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, 0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 5
glm::vec3(-0.9f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 6
glm::vec3(-0.7f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, -0.1f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 6
glm::vec3(-0.9f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 7
glm::vec3(-0.7f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, -0.3f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 7
glm::vec3(-0.9f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 8
glm::vec3(-0.7f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, -0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 8
glm::vec3(-0.9f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 9
glm::vec3(-0.7f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, -0.7f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 9
glm::vec3(-0.9f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), //sor 9
glm::vec3(-0.7f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.5f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.3f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(-0.1f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.1f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.3f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.5f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.7f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.9f, -0.9f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),//sor 9
};
float a = 0.0f;
float b = 0.95f;
float b1 = -0.95f;
glm::vec3 vertices2[4];
void genSzakasz(float a) {
vertices2[0] = glm::vec3(-1.0f, a, 0.0f);
vertices2[1] = glm::vec3(1.0f, a, 0.0f);
vertices2[2] = glm::vec3(1.0f, 1.0f, 0.0f);
vertices2[3] = glm::vec3(1.0f, 1.0f, 0.0f);
}
float RandomCoordGenerator()
{
float r3 = COORDMIN + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (COORDMAX - COORDMIN)));
return r3;
}
GLfloat radius = 0.2f; // first
GLfloat centerx = RandomCoordGenerator();
GLfloat centery = RandomCoordGenerator();
GLfloat novX = 0.002f;
GLfloat novY = 0.005f;
GLdouble updateFrequency = 0.01f, lastUpdate;
void korSzin()
{
for (int i = 0; i < 100; i++)
{
linePoints.push_back(
glm::vec3(
0.0f, 1.0f, 0.0f));
}
}
void generatePoints()
{
for (int i = 0; i < 100; i++)
{
linePoints.push_back(
glm::vec3(
centerx + radius * cos(i * (2 * 3.14159 / 100)),
centery + radius * sin(i * (2 * 3.14159 / 100)),
0));
}
korSzin();
}
GLuint renderingProgram; //kor
GLuint renderingProgram2; //pontok
GLuint renderingProgram3; //szakasz
bool checkOpenGLError() {
bool foundError = false;
int glErr = glGetError();
while (glErr != GL_NO_ERROR) {
cout << "glError: " << glErr << endl;
foundError = true;
glErr = glGetError();
}
return foundError;
}
void printShaderLog(GLuint shader) {
int len = 0;
int chWrittn = 0;
char* log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char*)malloc(len);
glGetShaderInfoLog(shader, len, &chWrittn, log);
cout << "Shader Info Log: " << log << endl;
free(log);
}
}
void printProgramLog(int prog) {
int len = 0;
int chWrittn = 0;
char* log;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char*)malloc(len);
glGetProgramInfoLog(prog, len, &chWrittn, log);
cout << "Program Info Log: " << log << endl;
free(log);
}
}
string readShaderSource(const char* filePath) {
string content;
ifstream fileStream(filePath, ios::in);
string line = "";
while (!fileStream.eof()) {
getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
GLuint createShaderProgram() {
GLint vertCompiled;
GLint fragCompiled;
GLint linked;
string vertShaderStr = readShaderSource("vertexShader.glsl");
string fragShaderStr = readShaderSource("fragmentShader.glsl");
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
const char* vertShaderSrc = vertShaderStr.c_str();
const char* fragShaderSrc = fragShaderStr.c_str();
glShaderSource(vShader, 1, &vertShaderSrc, NULL);
glShaderSource(fShader, 1, &fragShaderSrc, NULL);
glCompileShader(vShader);
glCompileShader(vShader);
checkOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &vertCompiled);
if (vertCompiled != 1) {
cout << "vertex compilation failed" << endl;
printShaderLog(vShader);
}
glCompileShader(fShader);
checkOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &fragCompiled);
if (fragCompiled != 1) {
cout << "fragment compilation failed" << endl;
printShaderLog(fShader);
}
GLuint vfProgram = glCreateProgram();
glAttachShader(vfProgram, vShader);
glAttachShader(vfProgram, fShader);
glLinkProgram(vfProgram);
checkOpenGLError();
glGetProgramiv(vfProgram, GL_LINK_STATUS, &linked);
if (linked != 1) {
cout << "linking failed" << endl;
printProgramLog(vfProgram);
}
glDeleteShader(vShader);
glDeleteShader(fShader);
return vfProgram;
}
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
float szakasz_y_koord = 0.0f;
if (key == GLFW_KEY_W && action == GLFW_PRESS)
{
if (a <= b) {
a += 0.2f;
genSzakasz(a);
szakasz_y_koord = a;
GLuint offsetLoc = glGetUniformLocation(renderingProgram, "szakasz_y_koord"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram, offsetLoc, a);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
if (key == GLFW_KEY_S && action == GLFW_PRESS)
{
if (a >= b1) {
a -= 0.2f;
genSzakasz(a);
szakasz_y_koord = a;
GLuint offsetLoc = glGetUniformLocation(renderingProgram, "szakasz_y_koord"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram, offsetLoc, a);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
createShaderProgram();
}
genSzakasz(a);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void init(GLFWwindow* window) {
renderingProgram = createShaderProgram(); // minden mas
generatePoints();
genSzakasz(a);
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO1);
glGenVertexArrays(1, &VAO1);
glGenBuffers(1, &VBO2);
glGenVertexArrays(1, &VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 200 * sizeof(glm::vec3), linePoints.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
renderingProgram2 = createShaderProgram();
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * 200, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * 4, vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
Elsőként megadjuk ezt az azonosítószámot.
Utána az attribútum méretét (vec3, láttuk a shaderben).
Harmadik az adat típusa.
Negyedik az adat normalizálása, ez maradhat FALSE jelen példában.
Az attribútum értékek hogyan következnek egymás után? Milyen lépésköz után találom a következő vertex adatait?
Végül megadom azt, hogy honnan kezdődnek az értékek a pufferben. Most rögtön, a legelejétől veszem őket.*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)(100 * sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) * 2, (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) * 2, (void*)(sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)(2 * sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void cleanUpScene()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(renderingProgram);
}
void bounce(double currentTime) {
if (currentTime - lastUpdate >= updateFrequency)
{
y += inc1;
x += inc;
if (x > 1.5f) inc = -0.01; // jobb
if (x < -0.07f) inc = 0.01; //bal
if (y > 0.7f) inc1 = -0.01; // fennt
if (y < -0.9f) inc1 = 0.01; //lennt
GLuint offsetLoc = glGetUniformLocation(renderingProgram, "offsetX"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram, offsetLoc, x); // küldjük el az "x" értékét az "offsetX" számára
GLuint offsetLoc1 = glGetUniformLocation(renderingProgram, "offsetY"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram, offsetLoc1, y); // küldjük el az "x" értékét az "offsetX" számára
}
}
void display(GLFWwindow* window, double currentTime) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); // fontos lehet minden egyes alkalommal törölni!
glUseProgram(renderingProgram);
glBindVertexArray(VAO);
glPointSize(30.0f);
bounce(glfwGetTime());
glDrawArrays(GL_TRIANGLE_FAN, 0, 100);
glUseProgram(renderingProgram2);
glBindVertexArray(VAO1);
glPointSize(10.0f);
glDrawArrays(GL_POINTS, 0, 100);
glUseProgram(renderingProgram2);
glBindVertexArray(VAO2);
glPointSize(30.0f);
glDrawArrays(GL_LINE_LOOP, 0, 2);
glBindVertexArray(0);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, "Draw a Line", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback);
//glfwSetCursorPosCallback(window, cursorPosCallback);
glfwSetMouseButtonCallback(window, mouseButtonCallback);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
cleanUpScene();
glfwTerminate();
exit(EXIT_SUCCESS);
}
Here is my Vertex Shader:
#version 430
uniform float offsetX;
uniform float offsetY;
uniform float szakaszYkoord;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 color;
out vec3 myColor;
void main(void)
{
gl_Position = vec4(aPos.x + offsetX, aPos.y + offsetY + szakaszYkoord, aPos.z, 1.0);
if ( aPos.y > szakaszYkoord){
myColor = vec3(1.0, 1.0, 0.0);
} else {
myColor = vec3(1.0, 0.0, 0.0);
}
}
Here is my Fragment Shader:
#version 430
in vec3 myColor;
out vec4 color;
void main(void)
{
color = vec4(myColor, 1.0);
}
My question is why the color of the line is changing buts the color of the cubes not? What should I do in order to change the color of the cubes when the line is moving?
Pass the vertex coordinate from the vertex shader to the fragment shader and set the color per fragment instead of per vertex.
Vertex shader:
#version 430
uniform float offsetX;
uniform float offsetY;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 color;
out vec3 vPos;
void main(void)
{
vPos = aPos + vec3(offsetX, offsetY, 0.0);
gl_Position = vec4(vPos, 1.0);
}
Fragment shader
#version 430
uniform float szakasz_y_koord;
in vec3 vPos;
out vec4 color;
void main(void)
{
color = (vPos.y > szakasz_y_koord)
? vec4(1.0, 1.0, 0.0, 1.0)
: vec4(1.0, 0.0, 0.0, 1.0);
}
Uniform variables are stored in the default uniform block of the shader program. They use the same shader source code to generate 2 programs objects. You only need 1 program and can completely remove the 2nd program.
As long as you are using 2 programs, you have to change the uniform variable in both programs. Set "szakasz_y_koord" to -1.0 when the circle is drawn and set it to a when the dots are drawn:
void display(GLFWwindow* window, double currentTime) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); // fontos lehet minden egyes alkalommal törölni!
GLuint offsetLoc = glGetUniformLocation(renderingProgram, "szakasz_y_koord"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram, offsetLoc, -1.0);
glUseProgram(renderingProgram);
glBindVertexArray(VAO);
glPointSize(30.0f);
bounce(glfwGetTime());
glDrawArrays(GL_TRIANGLE_FAN, 0, 100);
GLuint offsetLoc2 = glGetUniformLocation(renderingProgram, "szakasz_y_koord"); // mutató az "offsetX" értékre
glProgramUniform1f(renderingProgram2, offsetLoc2, a);
glUseProgram(renderingProgram2);
glBindVertexArray(VAO1);
glPointSize(10.0f);
glDrawArrays(GL_POINTS, 0, 100);
glBindVertexArray(VAO2);
glPointSize(30.0f);
glDrawArrays(GL_LINE_LOOP, 0, 2);
glBindVertexArray(0);
}
I am writing a mini OpenGL program with instancing in it. But when I ran the code, only one instance was shown. I thought that it should be easy, but I failed. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <GL/glut.h>
#include <vector>
#include <fstream>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#define WIDTH 1280
#define HEIGHT 720
static const std::string vertexShader =
"#version 330 core\n"
"in vec3 position;\n"
"in vec3 color;\n"
"in ivec3 Glob_pos;\n"
"uniform mat4 MVP;\n"
"out vec3 ToFragColor;\n"
"void main(){\n"
" gl_Position = MVP * vec4(vec3(Glob_pos) + position,1.0);\n"
" ToFragColor = color;\n"
"}\n";
static const std::string fragmentShader =
"#version 330 core\n"
"in vec3 ToFragColor;\n"
"uniform vec3 Cam;\n"
"out vec3 out_color;\n"
"void main(){\n"
" out_color = ToFragColor;\n"
"}\n";
static const GLfloat CUBE_VERT[12*3*2*3] = {
-1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 0.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
-1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
//TOP
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 0.0f, -1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 0.0f, -1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 0.0f, -1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f
};
GLuint LoadShaders();
void setup(GLuint programID);
void render(GLuint programID);
void computeMatricesFromInputs(GLFWwindow* window);
GLuint vao, vbo, ib;
GLuint MatrixID;
GLuint CamID;
//For model view matrix calculation
glm::vec3 CamLoc = glm::vec3(0,0,-5);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float) WIDTH / (float)HEIGHT, 1.0f, 1000.0f);
glm::mat4 View = glm::lookAt(
CamLoc,
glm::vec3(0,0,0),
glm::vec3(0,1,0)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 mvp = Projection * View * Model;
glm::vec3 direction;
float horizontalAngle = 3.14f;
float verticalAngle = 0.0f;
float initialFoV = 45.0f;
float speed = 3.0f;
float mouseSpeed = 0.005f;
float mtimeScale = 0.1f;
float ktimeScale = 1.0f;
float FoV = initialFoV; //- 5 * glfwGetMouseWheel();
double lastPos[] = { 0,0 };
const glm::vec3 null = glm::vec3(0,0,0);
//For model view matrix calculation -- end
std::vector<int> instanceObj;
int main(int argc, char **argv){
glutInit(&argc, argv);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window;
window = glfwCreateWindow(WIDTH, HEIGHT, "DearDaniel's OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
glewExperimental = true;
glewInit();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
GLuint programID = LoadShaders();
MatrixID = glGetUniformLocation(programID, "MVP");
CamID = glGetUniformLocation(programID, "Cam");
glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LESS);
glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
setup(programID);
do{
glUseProgram(programID);
computeMatricesFromInputs(window);
render(programID);
glfwSwapBuffers(window);
glfwPollEvents();
} while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );
glDeleteProgram(programID);
return 0;
}
GLuint LoadShaders(){
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
char const * VertexSourcePointer = vertexShader.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
char const * FragmentSourcePointer = fragmentShader.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
void setup(GLuint programID) {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 12*3*2*3*sizeof(int), CUBE_VERT, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glGenBuffers(1, &ib);
glBindBuffer(GL_ARRAY_BUFFER, ib);
glVertexAttribPointer(2, 3, GL_INT, GL_FALSE, 3 * sizeof( int), (void*) 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribDivisor(2, 1);
glBindVertexArray(0);
}
void render(GLuint programID) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, ib);
instanceObj.clear();
for (int i = 0; i < 32; i+=2)
for (int j = 0; j < 32; j +=2)
for (int k = 0; k < 32; k +=2) {
instanceObj.push_back(i);
instanceObj.push_back(j);
instanceObj.push_back(k);
}
glBufferData(GL_ARRAY_BUFFER, sizeof(int)*instanceObj.size(), &instanceObj[0], GL_STATIC_DRAW);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
glUniform3f(CamID, CamLoc.x, CamLoc.y, CamLoc.z);
glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 16*16*16);
glBindVertexArray(0);
}
void computeMatricesFromInputs(GLFWwindow* window){
static double lastTime = glfwGetTime();
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
float hori = horizontalAngle + mouseSpeed * float( xpos - lastPos[0] ) * mtimeScale;
float vert = verticalAngle + mouseSpeed * float( ypos - lastPos[1] ) * mtimeScale;
horizontalAngle = hori;
if (vert > -3.14f/2.0f && vert < 3.14f/2.0f) verticalAngle = vert;
lastPos[0] = xpos;
lastPos[1] = ypos;
direction = glm::vec3 (
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f/2.0f),
0,
cos(horizontalAngle - 3.14f/2.0f)
);
glm::vec3 up = glm::cross( right, direction );
if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS) CamLoc += direction * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS) CamLoc -= direction * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS) CamLoc += right * deltaTime * speed * ktimeScale;
if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS) CamLoc -= right * deltaTime * speed * ktimeScale;
Projection = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
View = glm::lookAt(
CamLoc, // Camera is here
CamLoc+direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
lastTime = currentTime;
mvp = Projection * View;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%f ", mvp[i][j]);
}
printf("\n");
}
}
I used the following command to compile my code:
g++ miniGL.cpp -Wall -std=c++11 -L/usr/local/lib -pthread -lGLEW -lGLU -lGL -lglut -lglfw3 -ldl -lrt -lXrandr -lXxf86vm -lXi -lXinerama -lX11 -lXcursor -lglfw -o ogl
I was meant to render 16*16*16 cubes onto the screen, but only one has shown. I spent more than ten hours for debugging. Now I gave up and shamelessly seeking for help.
You have to use glVertexAttribIPointer, when defining the array of generic vertex attribute data, for the vertex attrbute in ivec3 Glob_pos;.
glVertexAttribPointer is for floating point attributes only (integral data will be converted to floating point).
See the Khronos group reference page for glVertexAttribPointer:
For glVertexAttribPointer, if normalized is set to GL_TRUE, it indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.
For glVertexAttribIPointer, only the integer types GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT are accepted. Values are always left as integer values.
Note, probably Glob_pos is never set and has always the same, but undefined value.
Since you don't use glGetAttribLocation to get the attribute indices for the vertex attributes (position, color, Glob_pos), you should use Layout Qualifiers:
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in ivec3 Glob_pos;
My ultimate goal is to render 1 million spheres of different sizes and colors at 60 fps. I want to be able to move the camera around the screen as well.
I have modified the code on this page of the tutorial I am studying to try to instance many spheres. However, I find that at as little as 64 spheres my fps falls below 60, and at 900 spheres my fps is a measly 4. My understanding of instancing is naive, but I believe that I should be getting more frames-per-second than this. 60 fps should be attainable with only 64 spheres. I believe that I am, in some way, causing the CPU and GPU to communicate more often than they should have to. So my question is: How do I instance so many objects (ideally millions) without causing the fps to fall low (ideally 60 fps)?
I am calculating fps by calculating (10 / time_elapsed) every 10 frames, where time_elapsed is the time that has elapsed since the last fps call. I am printing this out using printf on line 118 of my code.
I have been learning OpenGL through this tutorial and so I use 32-bit GLEW and 32-bit GLFW in Visual Studio 2013. I have 8 GB of RAM on a 64-bit operating system (Windows 7) with a 2.30 GHz CPU.
I have tried coding my own example based on the tutorial above. Source code:
(set line #2 to be the number of spheres to be instanced. Make sure line#2 has a whole-number square root. Set line 4 to be the detail of the sphere, the lowest it can go is 0. Higher number = more detailed.)
// Make sure NUM_INS is a square number
#define NUM_INS 1
// Detail up to 4 is probably good enough
#define SPHERE_DETAIL 4
#include <vector>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GL includes
#include "Shader.h"
// GLM Mathemtics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Properties
GLuint screenWidth = 800, screenHeight = 600;
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
std::vector<GLfloat> create_sphere(int recursion);
// The MAIN function, from here we start our application and run the Game loop
int main()
{
// Init GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Initialize GLEW to setup the OpenGL Function pointers
glewExperimental = GL_TRUE;
glewInit();
// Define the viewport dimensions
glViewport(0, 0, screenWidth, screenHeight);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Comment to remove wireframe mode
// Setup OpenGL options
glEnable(GL_DEPTH_TEST);
// Setup and compile our shader(s)
Shader shader("core.vs", "core.frag");
// Generate a list of 100 quad locations/translation-vectors
std::vector<glm::vec2> translations(NUM_INS);
//glm::vec2 translations[NUM_INS];
int index = 0;
GLfloat offset = 1.0f / (float)sqrt(NUM_INS);
for (GLint y = -(float)sqrt(NUM_INS); y < (float)sqrt(NUM_INS); y += 2)
{
for (GLint x = -(float)sqrt(NUM_INS); x < (float)sqrt(NUM_INS); x += 2)
{
glm::vec2 translation;
translation.x = (GLfloat)x / (float)sqrt(NUM_INS) + offset;
translation.y = (GLfloat)y / (float)sqrt(NUM_INS) + offset;
translations[index++] = translation;
}
}
// Store instance data in an array buffer
GLuint instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * NUM_INS, &translations[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// create 12 vertices of a icosahedron
std::vector<GLfloat> vv = create_sphere(SPHERE_DETAIL);
GLuint quadVAO, quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, vv.size() * sizeof(GLfloat), &vv[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
// Also set instance data
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisor(2, 1); // Tell OpenGL this is an instanced vertex attribute.
glBindVertexArray(0);
// For printing frames-per-second
float counter = 0;
double get_time = 0;
double new_time;
// Game loop
while (!glfwWindowShouldClose(window))
{
// Print fps by printing (number_of_frames / time_elapsed)
counter += 1;
if (counter > 10) {
counter -= 10;
new_time = glfwGetTime();
printf("fps: %.2f ", (10/(new_time - get_time)));
get_time = new_time;
}
// Check and call events
glfwPollEvents();
// Clear buffers
//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw 100 instanced quads
shader.Use();
glm::mat4 model;
model = glm::rotate(model, 0.0f, glm::vec3(1.0f, 0.0f, 0.0f));
// Camera/View transformation
glm::mat4 view;
GLfloat radius = 10.0f;
GLfloat camX = sin(glfwGetTime()) * radius;
GLfloat camZ = cos(glfwGetTime()) * radius;
view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// Projection
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 100.0f);
// Get the uniform locations
GLint modelLoc = glGetUniformLocation(shader.Program, "model");
GLint viewLoc = glGetUniformLocation(shader.Program, "view");
GLint projLoc = glGetUniformLocation(shader.Program, "projection");
// Pass the matrices to the shader
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, vv.size() / 3, NUM_INS); // 100 triangles of 6 vertices each
glBindVertexArray(0);
// Swap the buffers
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
std::vector<GLfloat> add_color(std::vector<GLfloat> sphere) {
// Add color
std::vector<GLfloat> colored_sphere;
for (GLint i = 0; i < sphere.size(); i+=9) {
colored_sphere.push_back(sphere[i]);
colored_sphere.push_back(sphere[i+1]);
colored_sphere.push_back(sphere[i+2]);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(sphere[i+3]);
colored_sphere.push_back(sphere[i+4]);
colored_sphere.push_back(sphere[i+5]);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(sphere[i+6]);
colored_sphere.push_back(sphere[i+7]);
colored_sphere.push_back(sphere[i+8]);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
colored_sphere.push_back(0.0f);
}
return colored_sphere;
}
std::vector<GLfloat> tesselate(std::vector<GLfloat> shape, int recursion) {
if (recursion > 0) {
std::vector<GLfloat> new_sphere = {};
for (GLint i = 0; i < shape.size(); i += 9) {
// 1.902113 approximately
GLfloat radius = sqrt(1.0f + pow((1.0f + sqrt(5.0f)) / 2.0f, 2));
// Every 9 points is a triangle. Take 1 triangle and turn it into 4 triangles.
GLfloat p_one[] = {shape[i], shape[i + 1], shape[i + 2]};
GLfloat p_two[] = {shape[i + 3], shape[i + 4], shape[i + 5]};
GLfloat p_thr[] = {shape[i + 6], shape[i + 7], shape[i + 8]};
GLfloat p_one_two[] = { (p_one[0] + p_two[0]) / 2.0f, (p_one[1] + p_two[1]) / 2.0f, (p_one[2] + p_two[2]) / 2.0f };
GLfloat p_one_thr[] = { (p_one[0] + p_thr[0]) / 2.0f, (p_one[1] + p_thr[1]) / 2.0f, (p_one[2] + p_thr[2]) / 2.0f };
GLfloat p_two_thr[] = { (p_two[0] + p_thr[0]) / 2.0f, (p_two[1] + p_thr[1]) / 2.0f, (p_two[2] + p_thr[2]) / 2.0f };
GLfloat r_one_two = sqrt((p_one_two[0]*p_one_two[0]) + (p_one_two[1]*p_one_two[1]) + (p_one_two[2]*p_one_two[2]));
GLfloat r_one_thr = sqrt((p_one_thr[0]*p_one_thr[0]) + (p_one_thr[1]*p_one_thr[1]) + (p_one_thr[2]*p_one_thr[2]));
GLfloat r_two_thr = sqrt((p_two_thr[0]*p_two_thr[0]) + (p_two_thr[1]*p_two_thr[1]) + (p_two_thr[2]*p_two_thr[2]));
GLfloat t_one_two[] = { radius * p_one_two[0] / r_one_two, radius * p_one_two[1] / r_one_two, radius * p_one_two[2] / r_one_two };
GLfloat t_one_thr[] = { radius * p_one_thr[0] / r_one_thr, radius * p_one_thr[1] / r_one_thr, radius * p_one_thr[2] / r_one_thr };
GLfloat t_two_thr[] = { radius * p_two_thr[0] / r_two_thr, radius * p_two_thr[1] / r_two_thr, radius * p_two_thr[2] / r_two_thr };
// Triangle 1:
new_sphere.push_back(p_one[0]);
new_sphere.push_back(p_one[1]);
new_sphere.push_back(p_one[2]);
new_sphere.push_back(t_one_two[0]);
new_sphere.push_back(t_one_two[1]);
new_sphere.push_back(t_one_two[2]);
new_sphere.push_back(t_one_thr[0]);
new_sphere.push_back(t_one_thr[1]);
new_sphere.push_back(t_one_thr[2]);
// Triangle 2:
new_sphere.push_back(p_two[0]);
new_sphere.push_back(p_two[1]);
new_sphere.push_back(p_two[2]);
new_sphere.push_back(t_one_two[0]);
new_sphere.push_back(t_one_two[1]);
new_sphere.push_back(t_one_two[2]);
new_sphere.push_back(t_two_thr[0]);
new_sphere.push_back(t_two_thr[1]);
new_sphere.push_back(t_two_thr[2]);
// Triangle 3:
new_sphere.push_back(p_thr[0]);
new_sphere.push_back(p_thr[1]);
new_sphere.push_back(p_thr[2]);
new_sphere.push_back(t_one_thr[0]);
new_sphere.push_back(t_one_thr[1]);
new_sphere.push_back(t_one_thr[2]);
new_sphere.push_back(t_two_thr[0]);
new_sphere.push_back(t_two_thr[1]);
new_sphere.push_back(t_two_thr[2]);
// Center Triangle:
new_sphere.push_back(t_one_two[0]);
new_sphere.push_back(t_one_two[1]);
new_sphere.push_back(t_one_two[2]);
new_sphere.push_back(t_one_thr[0]);
new_sphere.push_back(t_one_thr[1]);
new_sphere.push_back(t_one_thr[2]);
new_sphere.push_back(t_two_thr[0]);
new_sphere.push_back(t_two_thr[1]);
new_sphere.push_back(t_two_thr[2]);
}
return tesselate(new_sphere, recursion - 1);
}
printf("number of vertices to be rendered: %d || ", shape.size());
return shape;
}
std::vector<GLfloat> create_sphere(int recursion) {
// Define the starting icosahedron
GLfloat t_ = (1.0f + sqrt(5.0f)) / 2.0f;
std::vector<GLfloat> icosahedron = {
-1.0f, t_, 0.0f, -t_, 0.0f, 1.0f, 0.0f, 1.0f, t_,
-1.0f, t_, 0.0f, 0.0f, 1.0f, t_, 1.0f, t_, 0.0f,
-1.0f, t_, 0.0f, 1.0f, t_, 0.0f, 0.0f, 1.0f, -t_,
-1.0f, t_, 0.0f, 0.0f, 1.0f, -t_, -t_, 0.0f, -1.0f,
-1.0f, t_, 0.0f, -t_, 0.0f, -1.0f, -t_, 0.0f, 1.0f,
1.0f, t_, 0.0f, 0.0f, 1.0f, t_, t_, 0.0f, 1.0f,
0.0f, 1.0f, t_, -t_, 0.0f, 1.0f, 0.0f, -1.0f, t_,
-t_, 0.0f, 1.0f, -t_, 0.0f, -1.0f, -1.0f, -t_, 0.0f,
-t_, 0.0f, -1.0f, 0.0f, 1.0f, -t_, 0.0f, -1.0f, -t_,
0.0f, 1.0f, -t_, 1.0f, t_, 0.0f, t_, 0.0f, -1.0f,
1.0f, -t_, 0.0f, t_, 0.0f, 1.0f, 0.0f, -1.0f, t_,
1.0f, -t_, 0.0f, 0.0f, -1.0f, t_,-1.0f, -t_, 0.0f,
1.0f, -t_, 0.0f,-1.0f, -t_, 0.0f, 0.0f, -1.0f, -t_,
1.0f, -t_, 0.0f, 0.0f, -1.0f, -t_, t_, 0.0f, -1.0f,
1.0f, -t_, 0.0f, t_, 0.0f, -1.0f, t_, 0.0f, 1.0f,
0.0f, -1.0f, t_, t_, 0.0f, 1.0f, 0.0f, 1.0f, t_,
-1.0f, -t_, 0.0f, 0.0f, -1.0f, t_,-t_, 0.0f, 1.0f,
0.0f, -1.0f, -t_,-1.0f, -t_, 0.0f,-t_, 0.0f, -1.0f,
t_, 0.0f, -1.0f, 0.0f, -1.0f, -t_, 0.0f, 1.0f, -t_,
t_, 0.0f, 1.0f, t_, 0.0f, -1.0f, 1.0f, t_, 0.0f,
};
// Tesselate the icososphere the number of times recursion
std::vector<GLfloat> colorless_sphere = tesselate(icosahedron, recursion);
// Add color and return
return add_color(colorless_sphere);
}
Vertex Shader: (named core.vs)
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 offset;
out vec3 fColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position.x + offset.x, position.y + offset.y, position.z, 1.0f);
fColor = color;
}
Fragment Shader: (named core.frag)
#version 330 core
in vec3 fColor;
out vec4 color;
void main()
{
color = vec4(fColor, 1.0f);
}
Shader class: (named Shader.h)
#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
class Shader
{
public:
GLuint Program;
// Constructor generates the shader on the fly
Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try
{
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar * fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader Program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Uses the current shader
void Use()
{
glUseProgram(this->Program);
}
};
#endif
My ultimate goal is to render 1 million spheres of different sizes and colors at 60 fps.
This is an unreasonable expectation.
Let's say that each sphere consists of 50 triangles. Kinda small for a good sphere shape, but lets assume they're that small.
1 million spheres at 50 tris per sphere is 50 million triangles per frame. At 60 FPS, that's 3 billion triangles per second.
No commercially available GPU is good enough to do that. And that's just a 50 triangle sphere; your 4x tessellated icosahedron will be over 5,000 triangles.
Now yes, drawing 60 such spheres is only ~300,000 triangles per frame. But even that at 60 FPS is ~18 million triangles per second. Hardware does exist that can handle that many triangles, but it's very clearly a lot. And you're definitely not going to get 1 million of them.
This is not a matter of GPU/CPU communication or overhead. You're simply throwing more work at your GPU than it could handle. You might be able to improve a couple of things here and there, but nothing that's going to get you even one tenth of what you want.
At least, not with this overall approach.
For your particular case of wanting to draw millions of spheres, I would use raytraced impostors rather than actual geometry of spheres. That is, you draw quads, who's positions are generated by the vertex (or geometry) shader. You generate a quad per sphere, such that the quad circumscribes the sphere. Then the fragment shader does a simple ray-sphere intersection test to see if the fragment in question (from the direction of the camera view) hits the sphere or not. If the ray doesn't hit the sphere, you discard the fragment.
You would also need to modify gl_FragDepth to give the impostor the proper depth value, so that intersecting spheres can work.
I am trying to draw a simple cube for a homework assignment for a class but for some reason it isn't showing up.
I am using uniform blocks and modern OpenGL. I am sure I am not doing something correctly.
My complete code is below. The below example depends on GLEW + GLFW + GLM.
What I found interesting is that for my light and material uniform blocks I get the index but the uniform block for my MVP matrix I don't get the index.
Any ideas?
Here is the C++ code:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#ifndef OPENGL_INCLUDES_
#define OPENGL_INCLUDES_
#include "GL\glew.h"
#ifndef GLFW_INCLUDES_
#define GLFW_INCLUDES_
#if defined(_WIN32)
#include <Windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#elif defined(__linux__)
#include <X11/X.h>
#include <X11/extensions/Xrandr.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include "GLFW\glfw3.h"
#include "GLFW\glfw3native.h"
#endif
#endif
#ifndef GLM_INCLUDES_
#define GLM_INCLUDES_
#include <glm/glm.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#endif
GLFWwindow* MainWindow;
#ifdef _WIN32
HWND MainWindowWin32Handle;
#endif
GLint WindowWidth = 1024;
GLint WindowHeight = 768;
GLulong SizeDivizor = 1;
GLboolean RiftAvailable = false;
GLboolean UseApplicationWindowFrame = false;
GLuint MainOpenGLShaderProgramID;
GLuint MatricesUniformBlockID;
GLuint MatricesUniformBufferID;
GLuint LightsUniformBlockID;
GLuint LightsUniformBufferID;
GLuint MaterialsUniformBlockID;
GLuint MaterialsUniformBufferID;
glm::mat4 ViewMatrix;
glm::mat4 ViewModelMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 MVPMatrix;
glm::mat3 NormalMatrix;
class StandardCube;
std::vector<StandardCube> Cubes;
class StandardCube {
private:
GLfloat* Vertices;
GLfloat* Normals;
GLuint* Indices;
GLuint VAO;
glm::mat4 ModelMatrix;
public:
void LoadIntoOpenGL() {
Vertices = new GLfloat[72]
{
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f
};
Normals = new GLfloat[72] {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};
Indices = new GLuint[36] {0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint MeshBufferID;
glGenBuffers(1, &MeshBufferID);
glBindBuffer(GL_ARRAY_BUFFER, MeshBufferID);
GLuint TotalBufferData = (sizeof(GLfloat) * 72) + (sizeof(GLfloat) * 72);
glBufferData(GL_ARRAY_BUFFER, TotalBufferData, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, NULL, sizeof(GLfloat) * 72, Vertices);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 72, sizeof(GLfloat) * 72, Normals);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(sizeof(GLfloat) * 72));
glEnableVertexAttribArray(1);
GLuint IndexBufferID;
glGenBuffers(1, &IndexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 36, Indices, GL_STATIC_DRAW);
glBindVertexArray(NULL);
ModelMatrix = glm::mat4(1.0f);
}
void DrawMe() {
MVPMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix;
ViewModelMatrix = ViewMatrix * ModelMatrix;
NormalMatrix = glm::transpose(glm::inverse(glm::mat3(MVPMatrix)));
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBufferSubData(GL_UNIFORM_BUFFER, NULL, sizeof(glm::mat4), glm::value_ptr(MVPMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(ViewModelMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) + sizeof(glm::mat4), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL, 1);
glBindVertexArray(NULL);
}
};
static void GLFWKeyCallback(GLFWwindow* p_Window, GLint p_Key, GLint p_Scancode, GLint p_Action, GLint p_Mods) {
if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS) {
glfwSetWindowShouldClose(p_Window, GL_TRUE);
}
if (p_Key == GLFW_KEY_O && p_Action == GLFW_PRESS) {
glClearColor(0.2f, 0.1f, 0.3f, 1.0f);
}
if (p_Key == GLFW_KEY_I && p_Action == GLFW_PRESS) {
glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
}
}
static void GLFWWindowResizeCallBack(GLFWwindow* p_Window, GLint width, GLint height) {
//CurrentGLFWApplication->WindowResizeCallBack(p_Window, width, height);
}
static void GLFWMouseMovementCallBack(GLFWwindow* p_Window, GLdouble MouseX, GLdouble MouseY) {
//CurrentGLFWApplication->MouseMovementCallBack(p_Window, MouseX, MouseY);
}
static void GLFWFramebufferSizeCallback(GLFWwindow* window, GLint width, GLint height)
{
glViewport(0, 0, width, height);
}
int initializeGLFWGLEW() {
MainWindow = NULL;
if (!glfwInit())
{
fprintf(stderr, "GLFW failed to initialize.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
if (UseApplicationWindowFrame) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
if (!RiftAvailable) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
GLint MonitorCount;
GLFWmonitor** GLFW_Monitors = glfwGetMonitors(&MonitorCount);
GLFWmonitor* MonitorToUse;
switch (MonitorCount)
{
case 0:
printf("No monitors found, exiting.\n");
return EXIT_FAILURE;
break;
case 1:
printf("Two monitors expected, found only one, using primary...\n");
MonitorToUse = glfwGetPrimaryMonitor();
break;
case 2:
printf("Two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
break;
default:
printf("More than two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
}
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", MonitorToUse, NULL);
}
}
if (!MainWindow)
{
fprintf(stderr, "Could not determine OpenGL version; exiting.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(MainWindow);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return EXIT_FAILURE;
}
glfwSetInputMode(MainWindow, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetKeyCallback(MainWindow, GLFWKeyCallback);
glfwSetWindowSizeCallback(MainWindow, GLFWWindowResizeCallBack);
glfwSetCursorPosCallback(MainWindow, GLFWMouseMovementCallBack);
glfwSetFramebufferSizeCallback(MainWindow, GLFWFramebufferSizeCallback);
glfwSwapBuffers(MainWindow);
glfwPollEvents();
return EXIT_SUCCESS;
}
int prepareOpenGL() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
return EXIT_SUCCESS;
}
int loadShaders() {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Compile Vertex Shader
printf("Compiling Vertext Shader.\n\n");
char const * VertexSource = "#version 330 \n\n\
layout(std140) uniform MatrixInformation {\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\n\
in vec4 position;\n\
in vec3 normal;\n\
\n\
\n\
out Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataOut;\n\
\n\
void main() {\n\
\n\
DataOut.normal = normalize(m_normal * normal);\n\
DataOut.eye = -(m_viewModel * position);\n\
\n\
gl_Position = m_pvm * position;\n\
}\n\
\n";
glShaderSource(VertexShaderID, 1, &VertexSource, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
GLint Result = GL_FALSE;
int InfoLogLength;
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
printf("Compiling Fragment Shader.\n\n");
char const * FragmentSource = "#version 330\n\
layout(std140) uniform Materials {\n\
vec4 diffuse;\n\
vec4 ambient;\n\
vec4 specular;\n\
vec4 emissive;\n\
float shininess;\n\
int texCount;\n\
};\
\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\
\n\
in Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataIn;\n\
\n\
out vec4 colorOut;\
\n\
void main() {\n\
\n\
vec4 spec = vec4(0.0);\n\
\n\
vec3 n = normalize(DataIn.normal);\n\
vec3 e = normalize(vec3(DataIn.eye));\n\
\n\
float intensity = max(dot(n, l_dir), 0.0);\n\
\n\
if (intensity > 0.0) {\n\
vec3 h = normalize(l_dir + e);\n\
\n\
float intSpec = max(dot(h, n), 0.0);\n\
spec = specular * pow(intSpec, shininess);\n\
}\n\
\n\
colorOut = max(intensity * diffuse + spec, ambient);\n\
}";
glShaderSource(FragmentShaderID, 1, &FragmentSource, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking shader program.\n\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::string ErrorMessage = std::string(&ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
MainOpenGLShaderProgramID = ProgramID;
return EXIT_SUCCESS;
}
int prepareShaderUniforms() {
glUseProgram(MainOpenGLShaderProgramID);
LightsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Lights");
glUniformBlockBinding(MainOpenGLShaderProgramID, LightsUniformBlockID, 2);
glGenBuffers(1, &LightsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, LightsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, LightsUniformBufferID);
GLfloat LightDirection[3] = { 1.0f, 1.0f, 0.0f };
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDirection), &LightDirection, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MatricesUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "MatrixInformation");
glUniformBlockBinding(MainOpenGLShaderProgramID, MatricesUniformBlockID, 1);
glGenBuffers(1, &MatricesUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MaterialsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Materials");
glUniformBlockBinding(MainOpenGLShaderProgramID, MaterialsUniformBlockID, 3);
glGenBuffers(1, &MaterialsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MaterialsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, MaterialsUniformBufferID);
GLfloat Material[18];
//Diffuse
Material[0] = 0.5f;
Material[1] = 0.0f;
Material[2] = 0.0f;
Material[3] = 1.0f;
//Ambient
Material[4] = 0.2f;
Material[5] = 0.2f;
Material[6] = 0.2f;
Material[7] = 1.0f;
//Specular
Material[8] = 0.0f;
Material[9] = 0.0f;
Material[10] = 0.0f;
Material[11] = 1.0f;
//Emissive
Material[12] = 0.0f;
Material[13] = 0.0f;
Material[14] = 0.0f;
Material[15] = 1.0f;
//Shininess
Material[16] = 2.0f;
//Texture Count
Material[17] = 0.0f;
glBufferData(GL_UNIFORM_BUFFER, sizeof(Material), &Material, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
return EXIT_SUCCESS;
}
int loadCubes() {
StandardCube NewCube;
NewCube.LoadIntoOpenGL();
Cubes.push_back(NewCube);
return EXIT_SUCCESS;
}
int prepareMatricies() {
GLfloat AspectRatio = (GLfloat)(WindowWidth) / (GLfloat)(WindowHeight);
ProjectionMatrix = glm::perspective(45.0f, AspectRatio, 1.0f, 1000.0f);
ViewMatrix = glm::lookAt(
glm::vec3(4.0f, 3.0f, 3.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, 0.0f), // and looks at the origin - What point the camera is looking at inside world.
glm::vec3(0.0f, 1.0f, 0.0f)// head is up(set to 0,1,0) - the direction of up for camera.
);
glViewport(0, 0, WindowWidth, WindowHeight);
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
if (initializeGLFWGLEW() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareOpenGL() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadShaders() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareShaderUniforms() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadCubes() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareMatricies() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(MainWindow))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto & C : Cubes) {
C.DrawMe();
}
glfwSwapBuffers(MainWindow);
glfwPollEvents();
}
exit(EXIT_SUCCESS);
}
Here is my vertex shader:
#version 330
layout(std140) uniform MatrixInformation {
mat4 m_pvm;
mat4 m_viewModel;
mat3 m_normal;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in vec4 position;
in vec3 normal;
out Data{
vec3 normal;
vec4 eye;
} DataOut;
void main() {
DataOut.normal = normalize(m_normal * normal);
DataOut.eye = -(m_viewModel * position);
gl_Position = m_pvm * position;
}
And here is my fragment shader:
#version 330
layout(std140) uniform Materials {
vec4 diffuse;
vec4 ambient;
vec4 specular;
vec4 emissive;
float shininess;
int texCount;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in Data{
vec3 normal;
vec4 eye;
} DataIn;
out vec4 colorOut;
void main() {
vec4 spec = vec4(0.0);
vec3 n = normalize(DataIn.normal);
vec3 e = normalize(vec3(DataIn.eye));
float intensity = max(dot(n, l_dir), 0.0);
if (intensity > 0.0) {
vec3 h = normalize(l_dir + e);
float intSpec = max(dot(h, n), 0.0);
spec = specular * pow(intSpec, shininess);
}
colorOut = max(intensity * diffuse + spec, ambient);
}
So the issue is this part:
//Binding uniform buffer
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
//uploading to the unbound array buffer
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
So you need to change
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
to
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
Additionally uploading NULL doesn't work on my OpenGL driver (although it should), so I had to
std::array<unsigned char,sizeof(glm::mat4)*2+sizeof(glm::mat3)> buff;
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, buff.data(), GL_DYNAMIC_DRAW);
As for how you would find that out: the old-school method is to litter your code with glGetError calls that only go off in debug mode. The more modern method is to create a debug context and print break on the callback to find out whereabouts the error is (then you can make glGetError calls in that area to get the exact function call if you don't know it by then, since modern OpenGL drivers are threaded and the callback may be triggered one or two function calls later).