I'm trying to draw a triangle using glDrawArrays function and gl Vertex, Color pointers.
The result is only black empty screen.
static const GLfloat vboData[] =
{ -0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
static const GLfloat colors[]={
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
};
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vboData);
glColorPointer(3, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glfwSwapBuffers(window);
glfwPollEvents();
}
Using VBO and VAO also doesn't work.
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
static const GLfloat vboData[] =
{ -0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
GLuint vbo;
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vboData), vboData, GL_STATIC_DRAW);
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
So, what I needed to get my code working is adding shaders to the project.
Here is minimal example.
This is my main.cpp
#include <iostream>
#include <fstream>
#include <algorithm>
#include "Loader.hpp"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLFWwindow *window;
int main(void)
{
//Viewport,window setup using GLFW;
if(!glfwInit()){
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(640, 480, "OpenGL Triangle", NULL, NULL);
if(!window){
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
//Loading and compiling shaders;
GLuint shaderID = LoadShader("vertexs.shader", "fragments.shader");
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
static const GLfloat vboData[] =
{ -1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
GLuint vbo;
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vboData), vboData, GL_STATIC_DRAW);
glUseProgram(shaderID); //Attaching shaders
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteBuffers(1, &vbo);
glDeleteProgram(shaderID);
glDeleteVertexArrays(1, &vao);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
Loader.hpp
#ifndef Loader_hpp
#define Loader_hpp
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLuint LoadShader(const char* vertex_file_path, const char* fragment_file_path);
#endif
Loader.cpp
#include "Loader.hpp"
GLuint LoadShader(const char * vertex_file_path,const char * fragment_file_path)
{
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open()){
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
else
{
printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
getchar();
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open())
{
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
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]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , 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]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\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]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
vertexs.shader (extension actually doesn't matter)
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
{
//We're not modifying positions of vertices
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
fragments.shader
#version 330 core
out vec3 color;
void main()
{
color = vec3(1,0,1);
}
I also found these tutorials extremely useful to make this solution, so the code above is partially taken from there.
Related
I have a "Hello Triangle" program I'm working on and can't for the life of me figure out why there is no color coming from the fragment shader. What is causing all fragments to output as white? I'm on Visual Studio 2019, program compiles just fine, and stepping through the debugger yields no results. I'm assuming the error is either in GLSL or my vertex attribute plumbing.
Vertex Shader:
#version 450 core
layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 color;
out vec4 fColor;
void main() {
fColor = color;
gl_Position = vPosition;
}
Fragment Shader:
#version 450 core
in vec4 fColor;
out vec4 fragColor;
void main() {
//fColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
fragColor = fColor;
}
Main:
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <string>
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
std::string readFile(const char* filePath) {
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
if (!fileStream.is_open()) {
std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while (!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void loadShaders(std::string filedir, GLenum type, GLuint &prog) {
GLenum errorVal;
std::string vertexSource = readFile("./vert.vert");
std::string fragmentSource = readFile("./frag.frag");
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = (const GLchar*)vertexSource.c_str();
glShaderSource(vertexShader, 1, &source, 0);
glCompileShader(vertexShader);
GLint isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(vertexShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar*)fragmentSource.c_str();
glShaderSource(fragmentShader, 1, &source, 0);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
// We don't need the shader anymore.
glDeleteShader(fragmentShader);
// Either of them. Don't leak shaders.
glDeleteShader(vertexShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
// Vertex and fragment shaders are successfully compiled.
// Now time to link them together into a program.
// Get a program object.
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(program);
// Don't leak shaders either.
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Use the infoLog as you see fit.
// In this simple program, we'll just leave
return;
}
// Always detach shaders after a successful link.
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
}
int main(int argc, char** argv) {
GLenum errorVal;
//glfw and gl3w initialization and window creation
glfwInit();
GLFWwindow* window = glfwCreateWindow(1920, 1080, "openGL bullshit", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();
//do shit here
GLuint VAOs[1];
GLuint bufferNames[1];
//vertices gets copied into the GPU, can be modified GPU-side using glMapData, glBufferSubData, or glNamedBufferStorage
GLfloat vertices[12][4] = {
{ -1.0f, 1.0f, 0.0f, 1.0f }, // Triangle 1
{ -1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 0.0f, 1.0f }, //Traingle 2
{ 1.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
{1.0f, 0.0f, 0.0f, 1.0f}, //colors
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f}
};
glCreateVertexArrays(1, VAOs);
glCreateBuffers(1, bufferNames);
glNamedBufferStorage(bufferNames[0], sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);
//glNamedBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);
//insert shader shit here
GLuint program = glCreateProgram();
loadShaders("./vert.vert", GL_VERTEX_SHADER, program); //ignore the inputs, they aren't used. This one command loads both vertex and fragment shaders
glUseProgram(program);
//binding and plumbing
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, bufferNames[0]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(sizeof(GLfloat) * 24));
//glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat) * 2));
//main loop
GLfloat debugArr[6][2];
while (!glfwWindowShouldClose(window)) {
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
vertices[0][0] += 0.0001f;
void *pointer = glMapNamedBuffer(bufferNames[0], GL_WRITE_ONLY);
memcpy(pointer, vertices, sizeof(vertices) / 12);
glUnmapNamedBuffer(bufferNames[0]);
glClearBufferfv(GL_COLOR, 0, black);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
//shutdown if main loop stops
glfwDestroyWindow(window);
glfwTerminate();
}
That is just undefined behavoir:
glNamedBufferStorage(bufferNames[0], sizeof(vertices) + sizeof(colors), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);
You tell the GL to read sizeof(vertices) + sizeof(colors) bytes beginning from the vertex array, but the memory after that array is completely unspecified. This might crash your program, or put random data into your buffer.
glBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);
This will just generate a GL_INVALID_ENUM error as glBufferSubData's first parameter is the binding target (like GL_ARRAY_BUFFER). So you never transfer the color data into the buffer. You need to use the DSA variant glNamedBufferSubData here.
Turns out the issue was with the program, when shaders were loaded it used a program variable that was baked into the load routine from the tutorial I used for that part, and I completely forgot about the program variable that passed as reference into the loadShaders function. Once the code was corrected to use the prog reference instead, all of the color came in!
I have written a very basic test setup to render a quad with glfw/glad.
I would expext it to draw a black quad in the middle of the window.
#include <iostream>
#include <array>
#include <cinttypes>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
using uint32 = std::uint32_t;
using gl_shader_id = GLuint;
gl_shader_id get_shader() {
constexpr auto vertex_shader_source = R"(
#version 460 core
layout (location = 0) in vec3 position;
void main() {
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
)";
constexpr auto fragment_shader_source = R"(
#version 460 core
out vec4 color;
void main() {
color = vec4(0.0, 0.0, 0.0, 1.0f);
}
)";
const auto vertex_shader = glCreateShader(GL_VERTEX_SHADER);
const auto fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
auto success = 0;
glShaderSource(vertex_shader, 1, &vertex_shader_source, nullptr);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
auto info_log = std::string{};
info_log.reserve(512);
glGetShaderInfoLog(vertex_shader, 512, nullptr, info_log.data());
std::cout << info_log << '\n';
assert(false); // Vertex shader compilation failed
}
glShaderSource(fragment_shader, 1, &fragment_shader_source, nullptr);
glCompileShader(fragment_shader);
if (!success) {
auto info_log = std::string{};
info_log.reserve(512);
glGetShaderInfoLog(fragment_shader, 512, nullptr, info_log.data());
std::cout << info_log << '\n';
assert(false); // Vertex shader compilation failed
}
const auto shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glDetachShader(shader_program, vertex_shader);
glDetachShader(shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
auto handle = glfwCreateWindow(800, 600, "Hello World", nullptr, nullptr);
glfwMakeContextCurrent(handle);
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress));
const auto shader_id = get_shader();
const auto vertices = std::array<glm::vec3, 4>{
glm::vec3{ -0.5f, -0.5f, 0.0f },
glm::vec3{ -0.5f, 0.5f, 0.0f },
glm::vec3{ 0.5f, -0.5f, 0.0f },
glm::vec3{ 0.5f, 0.5f, 0.0f }
};
const auto indices = std::array<uint32, 6>{
0, 1, 2,
1, 3, 2
};
auto vertex_array = 0u;
auto vertex_buffer = 0u;
auto index_buffer = 0u;
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);
glEnableVertexArrayAttrib(vertex_array, 0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), nullptr);
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint32), indices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(handle)) {
glfwPollEvents();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vertex_array);
glUseProgram(shader_id);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, nullptr);
glUseProgram(0);
glBindVertexArray(0);
glfwSwapBuffers(handle);
}
glfwDestroyWindow(handle);
glfwTerminate();
return 0;
}
The program and the shader code compile with no error/warnings.
When i execute the program i get the window which is cleared with the right color.
But the quad that i specified with the vertices and indices is not showing up.
I figgured it out after some fiddeling.
For anyone stumbeling uppon this problem.
You have to unbing the vertex array before unbinding the vertex buffer and index buffer.
Otherwise the binding stored inside the vertex array are going to be set to 0 and this nothing can be drawn
I have tried to create two rectangle objects with two different colors and moving in opposite direction. However, I am stuck in rendering the two rectangle with different colors (currently they are the same color).
What is the way to do it?
Here is the code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "ogldev_util.h"
#include "ogldev_math_3d.h"
GLuint VBO1;
GLuint VBO2;
GLuint gScaleLocation1;
GLuint gScaleLocation2;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
static float Scale1 = 0.0f;
Scale1 += 0.01f;
glUniform1f(gScaleLocation1, sinf(Scale1));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
static float Scale2 = 0.0f;
Scale2 -= 0.01f;
glUniform1f(gScaleLocation2, sinf(Scale2));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
glutIdleFunc(RenderSceneCB);
}
static void CreateVertexBuffer()
{
Vector3f Vertices[6];
Vertices[0] = Vector3f(1.0f, -0.5f, 0.0f);
Vertices[1] = Vector3f(1.0f, 0.5f, 0.0f);
Vertices[2] = Vector3f(3.0f, -0.5f, 0.0f);
Vertices[3] = Vector3f(1.0f, 0.5f, 0.0f);
Vertices[4] = Vector3f(3.0f, 0.5f, 0.0f);
Vertices[5] = Vector3f(3.0f, -0.5f, 0.0f);
glGenBuffers(1, &VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
Vector3f Vertices2[6];
Vertices2[0] = Vector3f(-3.0f, -0.5f, 0.0f);
Vertices2[1] = Vector3f(-3.0f, 0.5f, 0.0f);
Vertices2[2] = Vector3f(-1.0f, -0.5f, 0.0f);
Vertices2[3] = Vector3f(-3.0f, 0.5f, 0.0f);
Vertices2[4] = Vector3f(-1.0f, 0.5f, 0.0f);
Vertices2[5] = Vector3f(-1.0f, -0.5f, 0.0f);
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(1);
}
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0]= strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
string vs, fs;
if (!ReadFile(pVSFileName, vs)) {
exit(1);
};
if (!ReadFile(pFSFileName, fs)) {
exit(1);
};
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(ShaderProgram);
gScaleLocation1 = glGetUniformLocation(ShaderProgram, "gScale");
assert(gScaleLocation1 != 0xFFFFFFFF);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 05");
InitializeGlutCallbacks();
// Must be done after glut is initialized!
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
glutMainLoop();
return 0;
}
Fragment Shader
#version 330
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
It depends. Easiest way in this case is to add uniform vec3 color; and gl_FragColor = vec4(color, 1.0); inside your fragment shader and then initialize it with desired color by invoking glUniform3f before rendering of each rectangle. However, with rectangle count growth you would be better to create your vertex struct that will carry not only coordinates, but a color as well.
Also, I highly recommend this http://www.opengl-tutorial.org/ opengl tutorials web site.
I'm trying to learn SDL2, modern OpenGL, etc...
Below is the code I've adapted from tutorial for use with SDL2.
I have managed to get everything else to work, but for some reason the shader part crashes the program...
...I'm unable to get any console output to work (any tips on that?).
I'm using Eclipse.
Also if you find any other fixable spots on the code, please feel free to
point them out.
Program compiles without any errors or warnings.
#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
const int WINDOW_W = 1280;
const int WINDOW_H = 720;
const int WINDOW_X = 200;
const int WINDOW_Y = 200;
// FUNCTIONS
/* Shader loader:
* Handles loading GLSL vertex and fragment shaders
*/
GLuint ShaderLoad(const char * vertex_file_path, const char * fragment_file_path)
{
// Vertex shader ID
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
//Read the vertex shader files
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if (VertexShaderStream.is_open())
{
std::string Line = "";
while (getline(VertexShaderStream, Line))
{
VertexShaderCode += "\n" + Line;
}
VertexShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile vertex shader
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check vertex shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
// Fragment shader ID
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\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);
std::vector<char> ProgramErrorMessage(InfoLogLength);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
//GLuint programID = ShaderLoad("vshader.glsl", "fshader.glsl");
// Main
int main(int argc, char **argv)
{
//Variables
SDL_Window * SDLWindow = NULL;
SDL_GLContext GLContext;
SDL_Event event;
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
SDL_Init(SDL_INIT_EVERYTHING);
SDLWindow = SDL_CreateWindow("ELSA",
WINDOW_X, WINDOW_Y,
WINDOW_W, WINDOW_H,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
GLContext = SDL_GL_CreateContext(SDLWindow);
SDL_GL_MakeCurrent(SDLWindow, GLContext);
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetSwapInterval(1);
// OPENGL INIT
glewExperimental = GL_TRUE;
glewInit();
GLuint vertexbuffer;
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// 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);
while(true)
{
while (SDL_PollEvent(&event)) // Get all events per frame
{
if (event.type == SDL_QUIT)
{
return false;
}
if (event.type == SDL_WINDOWEVENT_RESIZED)
{
glViewport(0, 0,
SDL_GetWindowSurface(SDLWindow)->w,
SDL_GetWindowSurface(SDLWindow)->h);
}
}
//OpenGL code
glClearColor(0.15, 0.15, 0.30, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use shader
//glUseProgram(programID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(SDLWindow);
glDisableVertexAttribArray(0);
}
SDL_GL_DeleteContext(GLContext);
SDL_DestroyWindow(SDLWindow);
SDL_Quit();
return 0;
}
Ok Im trying to learn OpenGL 3.x, I used to use the old interface, and its not really going to well. Im using SDL2 for windowing and input.
What I would think the code should do is draw a red triangle on a blue background. The Problem is that it only does this sometimes, actually it seems to be completely random, sometimes it does that sometimes it just displays a black window.
I have no ideas as to why.
#include "SDL2/SDL.h"
#include "GL/glew.h"
GLuint makeShader(const char * shader, GLint t){
//---- Make Shader ----
GLuint s = glCreateShader(t);
glShaderSource(s, 1, &shader, NULL);
glCompileShader(s);
//---- Get Error Msg ----
int l=0;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &l);
char *msg = new char [l+1];
glGetShaderInfoLog(s, l, NULL, msg);
printf("Shader MSG: %s", msg);
delete [] msg;
return s;
}
int main(){
//----Init SDL & GL Context----
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *screen = SDL_CreateWindow("My Game Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
//1024, 768,
640, 480,
SDL_WINDOW_OPENGL);
SDL_GLContext glContext = SDL_GL_CreateContext(screen);
SDL_Event e;
//----Init GLEW---
glewExperimental=true;
GLenum err = glewInit();
if(GLEW_OK != err)
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
//----VAO----
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
//----Make Shaders----
const char *vscr = "#version 330 core\nlayout(location = 0) in vec4 position;\nvoid main(){gl_Position = position * 0.5; gl_Position.w = 1.0;}";
GLuint vshader = makeShader(vscr, GL_VERTEX_SHADER);
const char *fscr = "#version 330 core\nout vec3 color;\nvoid main(){ color = vec3(1,0,0);}";
GLuint fshader = makeShader(fscr, GL_FRAGMENT_SHADER);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, vshader);
glAttachShader(ProgramID, fshader);
glLinkProgram(ProgramID);
// ----make geometry----
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.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);
glViewport(0,0,640,480);
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
//----MAIN LOOP----
while(1){
glClear(GL_COLOR_BUFFER_BIT);
SDL_PollEvent(&e);
glUseProgram(ProgramID);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glFlush();
SDL_GL_SwapWindow(screen);
if(e.type == SDL_QUIT)
break;
}
SDL_GL_DeleteContext(screen);
return 0;
}