I have recently started learning OpenGL with the tutorial on http://www.opengl-tutorial.org. The first few tutorials went fine, and I got my triangle on the screen. Now I moved on to the cube tutorial, but I got stuck on the following problem. I only made 2 big changes to the triangle program to render my cube:
I changed the triangle to a cube by adding more vertices
I moved all of the initializing code from my main function into different other functions.
The problem is that when I run the program, it compiles fine and shows me a dark blue screen (the color I had set for clearing the screen), but it doesn't render my cube.
My full code is here:
#include "common/shader/loadShader.h"
#include "common/logpp/log++.h"
#include <GL\glew.h>
#include <GL\glfw3.h>
#include <vector>
logpp::FileLog mainLog;
//Contains all functions for initializing OpenGL, GLEW and GLFW
namespace GLInit
{
void SetGLFWWindowHints()
{
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); /*OpenGL 3.3*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
void InitGLFW()
{
if (!glfwInit())
{
logpp::Console::error("Failed to initialize GLFW!");
return;
}
SetGLFWWindowHints();
}
void InitGLEW()
{
glewExperimental = true; //Needed in core profile
if (glewInit() != GLEW_OK)
{
logpp::Console::error("Failed to initialize GLEW!");
return;
}
}
GLuint CreateVAO()
{
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
return VertexArrayID;
}
GLFWwindow* CreateWin(int width, int height, char const* caption)
{
auto window = glfwCreateWindow(width, height, caption, nullptr, nullptr);
if (window == nullptr)
{
std::string msg = "Failed to create window!";
logpp::Console::error(msg);
mainLog.write("[ERROR]: " + msg);
glfwTerminate();
return nullptr;
}
glfwMakeContextCurrent(window);
return window;
}
GLFWwindow* Init(int width, int height, char const* caption)
{
InitGLFW();
auto window = CreateWin(width, height, caption);
InitGLEW();
return window;
}
}
using namespace GLInit;
int main()
{
static const int VERTICES_IN_TRIANGLE = 3;
PathConverter::setBase(R"(C:\Users\michi_000\Desktop\C++\OpenGL\A Colored Cube\x64\Debug\)");
try
{
mainLog.open(PathConverter::convert("logs\\main.log"), false);
}
catch (logpp::FileLog::Exception e)
{
logpp::Console::error(e.what());
}
auto window = Init(800, 600, "A Colored Cube");
auto VertexArrayID = CreateVAO();
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
static const std::vector<GLfloat> cube //Vertices for the cube
{
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
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,
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
};
static const std::vector<GLfloat> cube_colors
{
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
/* static const std::vector<GLfloat> cube
{
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0,
0.0, 1.0, 0.0
};*/
static const std::vector<GLfloat>::size_type triangleCount = cube.size() / VERTICES_IN_TRIANGLE;
GLuint programID = LoadShaders(PathConverter::convert("shaders\\vertex.glsl").c_str(),
PathConverter::convert("shaders\\fragment.glsl").c_str());
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, cube.size(), &cube, GL_STATIC_DRAW);
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, cube_colors.size(), &cube_colors, GL_STATIC_DRAW);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
do
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0); //enable vertices
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, triangleCount, GL_FLOAT, GL_FALSE, 0, nullptr);
glDisableVertexAttribArray(0);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
nullptr // array buffer offset
);
glDisableVertexAttribArray(1);
logpp::Console::debug("Drawing triangles");
glDrawArrays(GL_TRIANGLES, 0, triangleCount);
// glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
} while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
&& !glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}
One last note, if I remove the color attribute and just set the entire cube to be red, it still gives the same dark blue screen.
There are several problems in the code:
You are disabling all vertex attributes before drawing. The calls to glDisableVertexAttribArray have to go after glDrawArrays, otherwise no data is attached when drawing.
The even better solution would be to move the VAO setup before the main-loop and never call glDisableVertexAttribArray at all. The pointers never change anyway, and storing the vertex attribute setup is exactly what a VAO is made for. Seems that the tutorial is very suboptimal in explaining/using them.
Another problem is that this line:
glVertexAttribPointer(0, triangleCount, GL_FLOAT, GL_FALSE, 0, nullptr);
should generate a GL_INVALID_VALUE error since the size (second parameter) is only allowed to be 1, 2, 3 or 4. In your case triangleCount equals 12. The size describes how many elements each of the vertices should consume. So if the attributes is of type vec3, then it should be 3.
You should always check if glGetError returns any errors before asking on SO. That saves a lot of time because you already know which line is problematic.
Also note, that triangleCount does not actually contain the triangle count but the number of vertices.
The first issue is that the 2nd paramter of glBufferData is the size of the buffer in bytes. Further operator & returns not a pointer to the data of a std::vector. You have to use std::vector::data():
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,
cube.size()*sizeof(GLfloat),
cube.data(),
GL_STATIC_DRAW);
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER,
cube_colors.size()*sizeof(GLfloat),
cube_colors.data(),
GL_STATIC_DRAW);
Further glDisableVertexAttribArray, disables the generic vertex attribute array. This has to be done after the drawing. The size parameter of
glVertexAttribPointer specifies the number of components per generic vertex attribute and must be 1, 2, 3, 4:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, triangleCount);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
Related
I don't have very much experience with OpenGL, GLFW, or GLEW so my troubleshooting ability with these libraries is slim to none. I have managed to render a triangle ([-1, -1, 0], [1, -1, 0], [0, 1, 0]) but when using the vertex attribute coordinates for a cube, along with color attributes it seems to not render. There could be a lot wrong with my code, the shaders, and my matrix operations. I wish I had a clearer understanding of what I'm doing so I could give a more descriptive account of my error. Currently the above code only renders the window. I followed https://learnopengl.com/ initially and got the first tutorials working, the following code is my "testing" file where I've attempted to reimplement some of the elements myself. There are lots of copy pasted portions that may be shared with that tutorial if it helps at all.
Any insight or suggestions would be appreciated very much.
Main Source
#include "global.hpp"
using namespace std;
using namespace glm;
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
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,
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
};
extern const char* VertexShader = R"(
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
uniform mat4 MVP;
out vec3 fragmentColor;
//out vec2 UV;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
//UV = vertexUV;
fragmentColor = vertexColor;
}
)";
extern const char* FragmentShader = R"(
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
//color = vec3(1,0,0);
color = fragmentColor;
}
)";
static const float tri_vertex_array[] = {
-.8, .8, 0,
-.8, -.8, 0,
.8, -.8, 0
};
int main()
{
if (!glfwInitFull()) {
printf("Unable To Init\n");
return 1;
}
uint width = 1200, height = 720;
GLFWwindow* window = glfwCreateWindow(width, height, "ME", 0, 0);
if (!window)
return -1;
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return 0;
//
GLuint VertexArrayId;
glGenVertexArrays(1, &VertexArrayId);
glBindVertexArray(VertexArrayId);
//
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
//glBufferData(GL_ARRAY_BUFFER, sizeof(tri_vertex_array), tri_vertex_array, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint colorBuffer;
glGenBuffers(1, &colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);
GLuint programId = glCreateProgram();
linkShader(programId, vertexShaderId);
linkShader(programId, fragmentShaderId);
// maybe nessacary?
//glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LESS);
glEnable(GL_CULL_FACE);
glViewport(0, 0, width, height);
//vec3 cameraPos = vec3(0.f, 0.f, 3.f);
//vec3 cameraTarget = vec3(0.f, 0.f, 0.f);
//vec3 cameraDirection = normalize(cameraPos - cameraTarget);
//
//vec3 up = vec3(0.f, 1.f, 0.f);
//vec3 right = normalize(
// cross(
// up,
// cameraDirection
// )
//);
//
//vec3 cameraUp = cross(cameraDirection, right);
//
//mat4 view = lookAt(
// vec3(4.f, 3.f, 3.f),
// vec3(0.f, 0.f, 0.f),
// vec3(0.f, 1.f, 0.f)
//);
mat4 projection = perspective(radians(45.f), width / (float)height, .1f, 100.f);
mat4 view = lookAt(
vec3(4, 3, -3),
vec3(0, 0, 0),
vec3(0, 1, 0)
);
mat4 model = mat4(1.0f); // identity
mat4 mvp = projection * view * model;
GLuint mvpId = glGetUniformLocation(programId, "MVP");
do {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.f, 0.f, .4f, 0.f);
glUseProgram(programId);
//gluLookAt(
// 4, 3, 3,
// 0, 0, 0,
// 0, 1, 0
//);
glUniformMatrix4fv(mvpId, 1, 0, &mvp[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
NULL
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glVertexAttribPointer(
1,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 3*12);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
} while (
!glfwWindowShouldClose(window)
&&
!glfwGetKey(window, GLFW_KEY_ESCAPE)
);
glfwTerminate();
}
global.hpp
#ifndef _glfw3_h_
// opengl extensions
#include <GL/glew.h>
// opengl utility / wrapper
#include <GLFW/glfw3.h>
// operations in space
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#endif // !_glfw3_h_
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <fstream>
#include <random>
#include <ctime>
#include <cmath>
static void glfwErrorCb(int errorCode, const char* error) {
printf("GLFW Error Thrown\n -> %d\n%s\n", errorCode, error);
}
static bool glfwInitFull() {
srand(time(0));
if (!glfwInit())
return 0;
glfwSetErrorCallback(glfwErrorCb);
glewExperimental = true;
glfwWindowHint(GLFW_SAMPLES, 4); // anti-aliasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // version
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // version
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // no-old-gl
return 1;
}
static GLuint compileShader(const char* content, GLenum type) {
GLuint shaderId = glCreateShader(type);
GLint returnValBuf;
glShaderSource(shaderId, 1, &content, NULL);
glCompileShader(shaderId);
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &returnValBuf);
if (returnValBuf == GL_FALSE) {
printf("Unable To Compile Shader\n```\n%s\n```\n\nInfo Log:\n", content);
GLint logLen;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetShaderInfoLog(shaderId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
return 0;
}
return shaderId;
}
static GLuint linkShader(GLuint programId, GLuint shaderId) {
glAttachShader(programId, shaderId);
glLinkProgram(programId);
GLint returnValBuf;
glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
if (returnValBuf == GLFW_FALSE) {
printf("Unable To Link Shader\nInfo Log:\n");
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
}
glDetachShader(programId, shaderId);
glDeleteShader(shaderId);
return programId;
}
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ullong;
#pragma once
The problem is that you call linkShader separately for each shader. It is possible to link a program multiple times. The function linkShader, however, attaches the shader to the program, linkes the program and detaches the shader from the program. Hence, the vertex and the fragment shader are never attached at the same time.
Attach the vertex and fragment shader and call linkShader once:
static GLuint linkShader(GLuint programId) {
glLinkProgram(programId);
GLint returnValBuf;
glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
if (returnValBuf == GLFW_FALSE) {
printf("Unable To Link Shader\nInfo Log:\n");
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
}
return programId;
}
int main()
{
// [...]
GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);
GLuint programId = glCreateProgram();
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
linkShader(programId);
glDetachShader(programId, vertexShaderId);
glDeleteShader(vertexShaderId);
glDetachShader(programId, fragmentShaderId);
glDeleteShader(fragmentShaderId);
// [...]
}
I was following an OpenGL tutorial and got to a point where I should pass color data to the vertex shader, but all I get is a black cube. I know that the fragment shader gets colors from the vertex shader because i tested it with setting the color vec3 to 1,0,0 and it worked.
Graphics Driver: Nvidia 388.13
OpenGL Version: 4.3
Drawing Cube:
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
/*--------------------------------------------------------------------------------------------------*/
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
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,
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
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
/*--------------------------------------------------------------------------------------------------*/
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 12*3);
glDisableVertexAttribArray(0);
/*--------------------------------------------------------------------------------------------------*/
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
/*--------------------------------------------------------------------------------------------------*/
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
/*--------------------------------------------------------------------------------------------------*/
mat4 Projection = perspective(radians(45.0f), (float)4 / (float)3, 0.1f, 100.0f);
mat4 View = lookAt(
vec3(x_Pos, y_Pos, z_Pos),
vec3(0, 0, 0), // looks at the origin
vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
mat4 Model = mat4((float)scale);
mat4 mvp = Projection * View * Model;
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
Main Loop:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) z_Pos -= 1;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) z_Pos += 1;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) y_Pos += 1;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) y_Pos -= 1;
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) scale += 0.01f;
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS && scale - 0.01f > 0) scale -= 0.01f;
glUseProgram(programID);
draw_Cube(x_Pos, y_Pos, z_Pos, scale, programID);
glfwSwapBuffers(window);
glfwPollEvents();
Vertex Shader:
#version 430 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
out vec3 fragmentColor;
uniform mat4 MVP;
void main() {
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
fragmentColor = vertexColor;
}
Fragment Shader:
#version 430 core
in vec3 fragmentColor;
out vec3 color;
void main(){
color = fragmentColor;
}
Minimal:
Main Loop:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_Cube(x_Pos, y_Pos, z_Pos, scale, programID);
glfwSwapBuffers(window);
glfwPollEvents();
Drawing Cube:
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 12*3);
glDisableVertexAttribArray(0);
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
};
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
mat4 Projection = perspective(radians(45.0f), (float)4 / (float)3, 0.1f, 100.0f);
mat4 View = lookAt(
vec3(4, 3, 3),
vec3(0, 0, 0), // looks at the origin
vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
mat4 Model = mat4(1.0f);
mat4 mvp = Projection * View * Model;
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
I can't remove from the shaders, I think.
I want to draw a cube to the screen that has random interpolated colors with OpenGL 4.1 and on OS X Yosemite. Whenever I run this program (it compiles fine), I get nothing, just a blank, blue screen. Here's my code:
#include <glm/gtc/matrix_transform.hpp>
#include <stdio.h>
#include "myglutils.hpp"
static const int vertices = 12 * 3;
static const GLfloat points[] = {
-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,
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
};
static const GLfloat colors[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
int main() {
if (!setupGLFW()) return 1;
setupApple();
glfwWindowHint(GLFW_SAMPLES, 4);
GLFWwindow* window = glfwCreateWindow(640, 480, "Colored Cube", NULL, NULL);
if (!window) {
fprintf(stderr, "Window creation failed.\n");
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
if (!setupGLEW()) return 1;
glClearColor(0.2, 0.0, 0.8, 1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLuint p_buffer;
glGenBuffers(1, &p_buffer);
glBindBuffer(GL_ARRAY_BUFFER, p_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
GLuint c_buffer;
glGenBuffers(1, &c_buffer);
glBindBuffer(GL_ARRAY_BUFFER, c_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, p_buffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, c_buffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
const char* vertex_shader =
"#version 410\n"
"layout(location = 0) in vec3 pos;"
"layout(location = 1) in vec3 in_color;"
"out vec3 color;"
"uniform mat4 MVP;"
"void main() {"
" gl_Position = MVP * vec4(pos, 1.0);"
" color = in_color;"
"}";
const char* fragment_shader =
"#version 410\n"
"in vec3 color;"
"out vec4 frag_color;"
"void main() {"
" frag_color = vec4(color, 1.0);"
"}";
GLuint shader = getShader(vertex_shader, fragment_shader);
GLuint MVPID = glGetUniformLocation(shader, "MVP");
//START MAKE MATRIX
glm::mat4 projection = glm::perspective(45.0, 4.0 / 3.0, 0.1, 100.0);
glm::mat4 view = glm::lookAt(glm::vec3(4.0, 3.0, -3.0), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
glm::mat4 MVP = projection * view;
//END MAKE MATRIX
glUniformMatrix4fv(MVPID, 1, GL_FALSE, &MVP[0][0]);
while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS) {
//START DRAW
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices);
//END DRAW
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
The problem is not with setupGLFW(), setupApple(), setupGLEW(), or getShader(). Those have been tested and proven to work. The problem lies somewhere else, but I cannot figure out where.
If you move your glUniformMatrix4fv() call in update loop just after glUseProgram(theProgram) call code should work (just worked at my PC).
Also you could move glUseProgram(theProgram) and glUniformMatrix4fv() out of render loop so they won't be executed each frame.
If you don't want to update your uniforms every glUseProgram, take a look at Uniform Buffer Object (related thread on SO). You can share Uniform Buffer Objects between shader programs and update them on demand.
I'm trying to collect all pixels color, than change same color and at the end render!
I searched for that and the results are:
glReadPixels() and glDrawPixels(), glReadPixels() works fine but glDrawPixels() not!
The problem is I have info in the array filled by glReadPixels but how can I pass this to OpenGL for render?
I tried to use glDrawPixels() but it doesn't work, neither with an array filled with red color (1,0,0);
do{
int size = 1024*768*3;
std::vector<GLfloat> pixel(size);
for (int i = 0; i< size; i+=3)
pixel[i] = 1.0;
glWritePixels(1024, 768, GL_RGB, GL_FLOAT, &pixel[0]);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
So searching again, and I found a tutorial on how render on a texture:
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <windows.h>
// Include GLEW
#include <glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
using namespace glm;
#include "shader.hpp"
int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Cube", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
//glDepthFunc(GL_LESS);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "TransformVertexShader.vertexshader", "ColorFragmentShader.fragmentshader" );
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,-3), // Camera is at (4,3,-3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-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,
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
};
// One color for each vertex. They were generated randomly.
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f,
0.583f, 0.771f, 0.014f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glUseProgram(programID);
// ---------------------------------------------
// Render to Texture - specific code begins here
// ---------------------------------------------
// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
// The texture we're going to render to
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, renderedTexture);
// Give an empty image to OpenGL ( the last "0" means "empty" )
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, 1024, 768, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Poor filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// The depth buffer
GLuint depthrenderbuffer;
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
//----------------------------
// Set "renderedTexture" as our colour attachement #0
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
// Always check that our framebuffer is ok
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
printf("\nFrameBuffer Error\n");
return false;
}
// The fullscreen quad's FBO
static const GLfloat g_quad_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
GLuint quad_vertexbuffer;
glGenBuffers(1, &quad_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
// Create and compile our GLSL program from the shaders
GLuint quad_programID = LoadShaders( "Passthrough.vertexshader", "WobblyTexture.fragmentshader" );
GLuint texID = glGetUniformLocation(quad_programID, "renderedTexture");
do{
// Render to our framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glViewport(0,0,1024,768); // Render on the whole framebuffer, complete from the lower left corner to the upper right
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0,1024,768); // Render on the whole framebuffer, complete from the lower left corner to the upper right
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(quad_programID);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
// Set our "renderedTexture" sampler to user Texture Unit 0
glUniform1i(texID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &colorbuffer);
glDeleteProgram(programID);
glDeleteFramebuffers(1, &FramebufferName);
glDeleteTextures(1, &renderedTexture);
glDeleteRenderbuffers(1, &depthrenderbuffer);
glDeleteBuffers(1, &quad_vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
But again I don't know how access to pixels before render them on screen, in the previous example I think all data are store in FrameBufferName variable, but how can I access to this buffer and take all the pixels color data?
I've tried all. Following OpenGL tutorials from http://www.opengl-tutorial.org/beginners-tutorials/.
On tutorial 4 it's asked to do a double model on your on. But I can't render the triangle and the cube at the same time (triangle doesn't appeared). Just did everything the same, changing the name of the variables related to the triangle. I didn't found in any other site the answers on this OPenGL 3.3 syntax, just found on completely different syntax (I don't want to change the way I do thins every time I found a error - it's like changing everything just after any error. For me doesn't make any sense).
Code it's a little big, but many of the things are just to open the Window and run the main loop (and the cube coordinates. They aren't a VBO. I'll learn later):
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW. Always include it before gl.h and glfw.h, since it's a bit magic.
#include <GL/glew.h>
// Include GLFW
#include <GL/glfw.h>
// Include GLM
#include <glm/glm.hpp>
#include "common/shader.hpp"
#include <iostream>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;
using namespace glm;
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GL/glfw.h>
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.hpp>
int main(int argc, char *argv[] )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); // 4x antialiasing
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
// Open a window and create its OpenGL context
if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
{
fprintf( stderr, "Failed to open GLFW window\n" );
glfwTerminate();
return -1;
}
// Initialize GLEW
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "TransformVertexShader.vertexshader", "ColorFragmentShader.fragmentshader" );
//Perspective Matrix
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
mat4 Projection = perspective(45.0f, 4.0f/3.0f, 0.1f, 100.0f);
// Camera matrix
mat4 View = lookAt(
vec3(4,3,-3), // Camera is at (4,3,3), in World Space
vec3(0,0,0), // and looks at the origin
vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
mat4 Model = mat4(1.0f); // Changes for each model !
// Our ModelViewProjection : multiplication of our 3 matrices
mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
// Get a handle for our "MVP" uniform.
// Only at initialisation time.
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
mat4 triangle_Model = mat4(1.0f);
mat4 triangle_MPV = Projection * View * triangle_Model;
GLuint triangle_MatrixID = glGetUniformLocation(programID, "MPV");
glUniformMatrix4fv(triangle_MatrixID, 1, GL_FALSE, &triangle_MPV[0][0]);
static const GLfloat triangle_buffer_data[] = {
-2.0f, -3.0f, 1.0f,
2.0f, -3.0f, 1.0f,
0.0f, 3.0f,-1.0f
};
// This will identify our vertex buffer
GLuint triangle_vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &triangle_vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, triangle_vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_buffer_data), triangle_buffer_data, GL_STATIC_DRAW);
// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
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,
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
};
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
// One color for each vertex. They were generated randomly.
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glfwSetWindowTitle( "Tutorials" );
// Dark blue background
glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
// Ensure we can capture the escape key being pressed below
glfwEnable( GLFW_STICKY_KEYS );
//main loop
do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
//First Attribute: Draw a Cube
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles -> 6 squares
glDisableVertexAttribArray(0);
//3rd attribute: draw a triangle
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, triangle_vertexbuffer);
glVertexAttribPointer(
2,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES,0,3);
glDisableVertexAttribArray(2);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(triangle_MatrixID, 1 ,GL_FALSE, &triangle_MPV[0][0]);
// Swap buffers
glfwSwapBuffers();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
glfwGetWindowParam( GLFW_OPENED ) );
glfwTerminate();
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteBuffers(1, &triangle_vertexbuffer);
glDeleteBuffers(1, &colorbuffer);
return EXIT_SUCCESS;
}
And, I don't think that this is the problem (tutorial said that it needed 1 shader and on the cube it worked perfectly), but I'll post the shaders code here too:
Collor Fragment shader:
#version 330 core
// Interpolated values from the vertex shaders
in vec3 fragmentColor;
// Ouput data
out vec3 color;
void main(){
// Output color = color specified in the vertex shader,
// interpolated between all 3 surrounding vertices
color = fragmentColor;
}
TransformVertexShadder:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
// Output data ; will be interpolated for each fragment.
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
// The color of each vertex will be interpolated
// to produce the color of each fragment
fragmentColor = vertexColor;
}
Can anyone help-me?
I don't think you can output the fragment color as a vec3, I use vec4(color, 1.0) in most cases.