How to draw Two Cubic Bezier Curve using 8 Points
The last point of the first curve will be the starting point of second curve
What I am doing wrong ??
Please Help me solve this issue .
#include <array>
#include <fstream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <iostream>
#include <math.h>
#include <string>
#include <vector>
using namespace std;
std::vector<glm::vec3> pointToDraw;
std::vector<glm::vec3> myControlPoints = {
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.0f, 0.0f),
};
#define numVBOs 1
#define numVAOs 1
GLuint VBO[numVBOs];
GLuint VAO[numVAOs];
GLuint renderingProgram;
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);
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);
}
// Shader program objektum létrehozása. Eltároljuk az ID értéket.
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;
}
int NCR(int n, int r) {
if (r == 0) return 1;
if (r > n / 2) return NCR(n, n - r);
long res = 1;
for (int k = 1; k <= r; ++k) {
res *= n - k + 1;
res /= k;
}
return res;
}
GLfloat blending(GLint n, GLint i, GLfloat t) {
return NCR(n, i) * pow(t, i) * pow(1.0f - t, n - i);
}
void drawBezierCurve(std::vector<glm::vec3> controlPoints) {
glm::vec3 nextPoint;
GLfloat t = 0.0f, B;
GLfloat increment = 1.0f / 100.0f;
while (t <= 1.0f) {
nextPoint = glm::vec3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < controlPoints.size(); i++) {
B = blending(controlPoints.size() - 1, i, t);
nextPoint.x += B * controlPoints.at(i).x;
nextPoint.y += B * controlPoints.at(i).y;
nextPoint.z += B * controlPoints.at(i).z;
}
pointToDraw.push_back(nextPoint);
t += increment;
}
}
void init(GLFWwindow* window) {
renderingProgram = createShaderProgram();
drawBezierCurve(myControlPoints);
glGenBuffers(numVBOs, VBO);
glGenVertexArrays(numVAOs, VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, pointToDraw.size() * sizeof(glm::vec3), pointToDraw.data(), GL_STATIC_DRAW);
glBindVertexArray(VAO[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(renderingProgram);
glClearColor(0.0, 0.0, 0.0, 1.0);
}
void display(GLFWwindow* window, double currentTime) {
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO[0]);
glLineWidth(2.0f);
glDrawArrays(GL_LINE_STRIP, 0, pointToDraw.size());
glBindVertexArray(0);
}
I want to join two cubic Bezier curve
Two Cubic Bezier Curve Sample
Second curve is starting from the end of first cubic Bezier curve
Related
I'm making an OpenGL program. However, whenever I run it, the "vertexIn" attribute of the shader returns negative when getting its location. I've searched several stack overflow posts as well as docs and other websites. Still, I could not find any reason as to why vertexIn returns negative when OpenGL tries to get its location, given that in other working examples, it is used in the same way I use it.
Edited the post to have more code in main so it's able to be reproduced.
Main.cpp
#include <SDL.h>
#include <math.h>
#include "Header Files/Shader.h"
Shader shader;
bool isAppRunning{ true };
SDL_Window* window{ nullptr };
SDL_GLContext context{ nullptr };
GLuint VAO{ 0 };
GLuint EBO{ 0 };
GLuint vertexVBO{ 0 };
GLuint colorVBO{ 0 };
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1)
{
std::cout << "SDL did not initialize properly." << std::endl;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
window = SDL_CreateWindow("OpenGL Project", 320, 180, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window)
{
std::cout << "OpenGL Window was not created properly." << std::endl;
}
context = SDL_GL_CreateContext(window);
if (!context)
{
std::cout << "OpenGL context could not be created properly! The context is either invalid or not supported by your graphics card! Please try on Another PC!" << std::endl;
}
if (!gladLoaderLoadGL())
{
std::cout << "Error loading OpenGl extensions." << std::endl;
}
Shader::Initialize();
shader.Create("../OpenGl/Shader Files/Shader.vert", "../OpenGl/Shader Files/Shader.frag");
shader.Use();
GLfloat vertices[] = { -0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f };
GLfloat colours[] = { 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f };
GLuint indices[] = { 0, 1, 3,
3, 1, 2 };
auto vertexAttributeID = shader.GetAttributeID("vertexIn");
auto colourAttributeID = shader.GetAttributeID("colorIn");
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &vertexVBO);
glGenBuffers(1, &colorVBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(vertexAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertexAttributeID);
glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glVertexAttribPointer(colourAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(colourAttributeID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
while (isAppRunning)
{
SDL_Event events;
while (SDL_PollEvent(&events))
{
switch (events.type)
{
//close the window
case SDL_QUIT:
{
isAppRunning = false;
break;
}
}
}
glClearColor(191 / 255.0f, 87 / 255.0f, 205 / 255.0f, 255 / 255.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
glDeleteBuffers(1, &EBO);
glDeleteBuffers(1, &colorVBO);
glDeleteBuffers(1, &vertexVBO);
glDeleteVertexArrays(1, &VAO);
glDisableVertexAttribArray(colourAttributeID);
glDisableVertexAttribArray(vertexAttributeID);
shader.Destroy();
Shader::Shutdown();
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit;
return 0;
}
Shader.cpp
#include "Header Files/Shader.h"
GLint Shader::vertexShaderID = 0;
GLint Shader::fragmentShaderID = 0;
bool Shader::Initialize()
{
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
if (vertexShaderID == 0)
{
std::cout << "Error! Vertex Shader could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (fragmentShaderID == 0)
{
std::cout << "Error! Fragment Shader could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
return true;
}
void Shader::Shutdown()
{
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
}
GLuint Shader::GetUniformID(const std::string& uniform) const
{
auto ID = glGetUniformLocation(programID, uniform.c_str());
assert(ID != -1);
return ID;
}
GLuint Shader::GetAttributeID(const std::string& attribute) const
{
auto ID = glGetAttribLocation(programID, attribute.c_str());
assert(ID != -1);
return ID;
}
bool Shader::Create(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename)
{
programID = glCreateProgram();
if (programID == 0)
{
std::cout << "Error! Shader Program could not be created! This could be because of your Graphics Card not supporting modern OpenGL!" << std::endl;
return false;
}
if (!CompileShaders(vertexShaderFilename))
{
return false;
}
if (!CompileShaders(fragmentShaderFilename))
{
return false;
}
if (!LinkProgram())
{
return false;
}
return true;
}
bool Shader::SendData(const std::string& uniform, GLint data)
{
glUniform1i(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLuint data)
{
glUniform1ui(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat data)
{
glUniform1f(GetUniformID(uniform), data);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y)
{
glUniform2f(GetUniformID(uniform), x, y);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z)
{
glUniform3f(GetUniformID(uniform), x, y, z);
return true;
}
bool Shader::SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
glUniform4f(GetUniformID(uniform), x, y, z, w);
return true;
}
void Shader::Use() const
{
glUseProgram(programID);
}
void Shader::Destroy() const
{
glDeleteProgram(programID);
}
bool Shader::LinkProgram()
{
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
glDetachShader(programID, vertexShaderID);
glDetachShader(programID, fragmentShaderID);
GLint linkResult = 0;
glGetProgramiv(programID, GL_LINK_STATUS, &linkResult);
if (linkResult == GL_FALSE)
{
GLchar error[1000];
GLsizei bufferSize = 1000;
glGetProgramInfoLog(programID, bufferSize, &bufferSize, error);
std::cout << "Error! Program did not link successfully! Error information down below: " << std::endl;
std::cout << error << std::endl;
return false;
}
std::cout << "Program Linked Successfully!" << std::endl;
return true;
}
bool Shader::CompileShaders(const std::string& filename)
{
std::ifstream file(filename);
//file.open(filename);
if (!file)
{
std::cout << "Error opening \"" + (filename)+"\"! File non - existent or unreachable! Make sure to check the spelling or the path!" << std::endl;
return false;
}
std::string line;
std::string sourceCode;
while (!file.eof())
{
std::getline(file, line);
sourceCode += line + "\n";
}
//file.close();
auto shaderID = (filename.find(".vert")) ? vertexShaderID : fragmentShaderID;
const GLchar* finalCode = reinterpret_cast<const GLchar*>(sourceCode.c_str());
//bind shader code with object
glShaderSource(shaderID, 1, &finalCode, nullptr);
//compile shader code
glCompileShader(shaderID);
GLint compileResult;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileResult);
if (compileResult == GL_FALSE)
{
GLchar error[1000];
GLsizei bufferSize = 1000;
glGetShaderInfoLog(shaderID, bufferSize, &bufferSize, error);
std::cout << "Error! Shader did not compile successfully! Error information down below: " << std::endl;
std::cout << error << std::endl;
return false;
}
std::cout << "Shader compiled successfully!" << std::endl;
return true;
}
Shader.h
#pragma once
#include <iostream>
#include <assert.h>
#include <fstream>
#include <string>
#include "gl.h"
class Shader
{
public:
static bool Initialize();
static void Shutdown();
GLuint GetUniformID(const std::string& uniform) const;
GLuint GetAttributeID(const std::string& attribute) const;
bool Create(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename);
bool SendData(const std::string& uniform, GLint data);
bool SendData(const std::string& uniform, GLuint data);
bool SendData(const std::string& uniform, GLfloat data);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
bool SendData(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void Use() const;
void Destroy() const;
private:
static GLint vertexShaderID;
static GLint fragmentShaderID;
GLuint programID{ 0 };
bool LinkProgram();
bool CompileShaders(const std::string& filename);
};
Shader.vert
#version 460
in vec3 vertexIn;
in vec3 colorIn;
out vec3 colorOut;
void main(void)
{
colorOut = colorIn;
gl_Position = vec4(vertexIn, 1.0);
}
Shader.frag
#version 460
in vec3 colorOut;
out vec4 pixelColor;
void main(void)
{
pixelColor = vec4(colorOut, 1.0);
}
so I got an exception thrown when I used the function glGenBuffer. can anyone help me to fix it?
P.S. I am using glad instead of glew.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;
unsigned int createShader(unsigned int shadertype, const char* shaderSource) {
unsigned int shader;
shader = glCreateShader(shadertype);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
int status;
char info[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
glGetShaderInfoLog(shader, 512, NULL, info);
cout << "FAILED TO COMPILE!\n" << info << '\n';
glDeleteShader(shader);
}
return shader;
}
unsigned int createShaderProgram(const char* VshaderSrc, const char* FshaderSrc) {
unsigned int vertexShader = createShader(GL_VERTEX_SHADER, FshaderSrc);
unsigned int fragmentShader = createShader(GL_FRAGMENT_SHADER, FshaderSrc);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
int status;
char info[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
if (!status) {
glGetProgramInfoLog(shaderProgram, 512, NULL, info);
cout << "FAILED TO LINK PROGRAM\n" << info << '\n';
}
return shaderProgram;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void closeWindow(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
void cobwebDiagmramForLogistics(float x0, float miu, float* ptr) {
*(ptr) = x0;
*(ptr + 1) = 0.0f;
*(ptr + 2) = 0.0f;
*(ptr + 3) = x0;
*(ptr + 4) = miu * x0 * (1.0f - x0);
*(ptr + 5) = 0.0f;
float x = x0;
for (int i = 1; i < 100; i++) {
float horPlot = miu * x * (1.0f - x);
*(ptr + i * 6) = horPlot;
*(ptr + i * 6 + 1) = horPlot;
*(ptr + i * 6 + 2) = 0.0f;
float verPlot = miu * horPlot * (1.0f - horPlot);
*(ptr + i * 6 + 3) = horPlot;
*(ptr + i * 6 + 4) = verPlot;
*(ptr + i * 6 + 5) = 0.0f;
x = verPlot;
}
}
int main() {
float CobwebPlot[606];
cobwebDiagmramForLogistics(0.2f, 3.6f, &CobwebPlot[0]);
unsigned int positions[1212];
for (int i = 0; i < 606; i++) {
positions[i] = i;
positions[i + 1] = i + 1;
}
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Cobweb_Diagram", NULL, NULL);
if (window == NULL) {
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
unsigned int cobwebBuffer;
unsigned int bufferArray;
unsigned int elementArray;
glGenVertexArrays(1, &bufferArray);
glGenBuffers(1, &cobwebBuffer);
glGenBuffers(1, &elementArray);
glBindBuffer(GL_ARRAY_BUFFER, cobwebBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(CobwebPlot), CobwebPlot, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArray);
glBufferData(GL_ELEMENT_ARRAY_BARRIER_BIT, sizeof(positions), positions,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 lineColor;\n"
"void main()\n"
"{\n"
" lineColor = vec4(1.0f, 0.1f, 0.2f, 1.0f)"
"}\n";
unsigned int shaderProgram =
createShaderProgram(vertexShaderSource, fragmentShaderSource);
glUseProgram(shaderProgram);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
cout << "Failed to initialize GLAD" << endl;
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window)) {
closeWindow(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(bufferArray);
glDrawElements(GL_LINE_STRIP, 1212, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) needs to be called before the very first OpenGL instruction. Call it right after glfwMakeContextCurrent(window):
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
cout << "Failed to initialize GLAD" << endl;
return -1;
}
There is also a problem in your shader code. A semicolon is missing at the end of lineColor = vec4(1.0f, 0.1f, 0.2f, 1.0f). I suggest using raw string literals:
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 lineColor;
void main()
{
lineColor = vec4(1.0f, 0.1f, 0.2f, 1.0f);
}
)";
I am trying to render a cylinder in OpenGL, by first starting to render top and lower caps using TRIANGLE_FAN. I store all the vertex data in one VBO and create two index buffers one for each cap. The top cap gets rendered correctly however the low cap does not get rendered at all, you can see it in the snapshot.
Here is my client application.
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
using namespace std;
#define PI 3.14159265359
static string ParseShader(string filepath) {
ifstream stream(filepath);
string line;
stringstream stringStream;
while (getline(stream, line))
{
stringStream << line << '\n';
}
return stringStream.str();
}
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str(); // this returns a pointer to data inside the string, the first character
glShaderSource(id, 1, &src, nullptr); // shader id, count of source codes, a pointer to the array that holds the strings
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
cout << type << endl;
cout << message << endl;
glDeleteShader(id);
return 0;
}
return id;
}
// takes the shader codes as a string parameters
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
GLuint program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program); // validate if the program is valid and can be run in the current state of opengl
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
std::vector<float> GenerateVertexData(float radius, float cylinderHeight, int vertexCount) {
int bufferSize = 3 * vertexCount;
std::vector<float> result(3 * vertexCount);
result[0] = 0;
result[1] = 0;
result[2] = cylinderHeight / 2;
float angleDelta = (360 / (vertexCount - 1)) * PI / 180;
float currentAngle = 0;
for (int i = 1; i < vertexCount; ++i) {
result[ 3 * i ] = cos(currentAngle) * radius;
result[3 * i + 1] = sin(currentAngle) * radius;
result[3 * i + 2] = cylinderHeight / 2;
currentAngle += angleDelta;
}
for (int i = 0; i < bufferSize; ++i) {
std::cout << "Result [ " << i << " ]" << result[i] << std::endl;
}
return result;
}
std::vector<GLuint> GenerateIndexData(int vertexCount) {
std::vector<GLuint> result(vertexCount + 1);
for (int i = 0; i < vertexCount; ++i) {
result[i] = i;
}
result[vertexCount] = 1;
return result;
}
std::vector<GLuint> GenerateLowCapIndexData(int vertexCount) {
std::vector<GLuint> result(vertexCount + 1);
for (int i = 0; i < vertexCount; ++i) {
result[i] = i + vertexCount;
std::cout << "Index [ " << i << " ]" << result[i] << std::endl;
}
result[vertexCount] = 1 + vertexCount;
std::cout << "Index [ " << result.size() << " ]" << result.back() << std::endl;
return result;
}
std::vector<GLuint> generateBodyIndexData(int verticalSegments) {
std::vector<GLuint> result(2 * (verticalSegments + 1));
for (int i = 0; i < verticalSegments; ++i) {
result[ 2 * i ] = i;
result[2 * i + 1] = i + verticalSegments;
}
result[result.size() - 2] = result.front();
result.back() = result[1];
return result;
}
int main(int argc, char* argv[]) {
float radius = std::stof(argv[1]);
float cylinderHeight = std::stof(argv[2]);
int verticalSegments = std::stoi(argv[3]);
std::cout << "Vertical segments : " << verticalSegments << std::endl;
int totalVertexCount = verticalSegments + 1;
const int vertexCoordinateCount = 3;
std::vector<float> vertexData = GenerateVertexData(radius, cylinderHeight, totalVertexCount);
std::vector<float> vertexDataLowerHalf = GenerateVertexData(radius, -cylinderHeight, totalVertexCount);
appendVec(vertexData, vertexDataLowerHalf);
std::vector<GLuint> topCapIndexData = GenerateIndexData(totalVertexCount);
std::vector<GLuint> lowCapIndexData = GenerateLowCapIndexData(totalVertexCount);
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
window = glfwCreateWindow(640, 480, "HW3", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
if (glfwRawMouseMotionSupported())
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
//Positions
GLuint positionBufferHandle;
glGenBuffers(1, &positionBufferHandle);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(float), vertexData.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, vertexCoordinateCount, GL_FLOAT, GL_FALSE, sizeof(float) * vertexCoordinateCount, 0);
glEnableVertexAttribArray(0);
//TopCap Indices
GLuint indexBufferHandle;
glGenBuffers(1, &indexBufferHandle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, topCapIndexData.size() * sizeof(GLuint), topCapIndexData.data(), GL_STATIC_DRAW);
//LowCap Indices
GLuint lowCapIndexBufferHandle;
glGenBuffers(1, &lowCapIndexBufferHandle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lowCapIndexBufferHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lowCapIndexData.size() * sizeof(GLuint), lowCapIndexData.data(), GL_STATIC_DRAW);
string vertexSource = ParseShader("vertex.shader");
string fragmentSource = ParseShader("fragment.shader");
unsigned int program = CreateShader(vertexSource, fragmentSource);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glDrawElements(GL_TRIANGLE_FAN, topCapIndexData.size() + lowCapIndexData.size(), GL_UNSIGNED_INT, nullptr);
//Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glDeleteProgram(program);
glfwTerminate();
return 0;
}
I have checked my vertex data generating functions and they are correct.
Here is the snapshot of my result.
Only 1 index buffer can be bound at a time. You need 2 draw calls and must bind the index buffer before the draw call:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle);
glDrawElements(GL_TRIANGLE_FAN, topCapIndexData.size(), GL_UNSIGNED_INT, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lowCapIndexBufferHandle);
glDrawElements(GL_TRIANGLE_FAN, lowCapIndexData.size(), GL_UNSIGNED_INT, nullptr);
Alternatively you can put the list of indices in 1 buffer and separate them with a Primitive Restart index.
GLuint restartIndex = 0xffffffff;
std::vector<GLuint> indices = topCapIndexData;
indices.push_back(restartIndex);
indices.insert(indices.end(), lowCapIndexBufferHandle.begin(), lowCapIndexBufferHandle.end();
GLuint indexBufferHandle;
glGenBuffers(1, &indexBufferHandle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(restartIndex);
glDrawElements(GL_TRIANGLE_FAN, indices.size(), GL_UNSIGNED_INT, nullptr);
I am new to OpenGl, right now my code can move a big circle with a small one inside him around the window.
Can you please tell me how to move the small circle separately from the big one, and also how to get him out from inside the big one.
And when for eg.: the small cirle is inside the big one when they are moving they moving together, and there is a line which is connects the center of the window with the small cirlce.
Here is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "glm/glm.hpp"
#include <array>
#include <iostream>
#include <string>
#include <fstream>
#define PI 3.14159265359
using namespace std;
#define numVAOs 1
GLuint VBO;
GLuint VAO;
GLfloat radius = 0.2;
GLfloat centerx = 0.3;
GLfloat centery = 0;
GLfloat novX = 0.009;
GLfloat novY = 0.005;
GLdouble updateFrequency = 0.01, lastUpdate;
GLfloat s_vertices[600];
void updateVertexData()
{
for (int i = 0; i < 100; i++)
{
s_vertices[3 * i] = centerx + radius * cos(i * (2 * PI / 100));
s_vertices[3 * i + 1] = centery + radius * sin(i * (2 * PI / 100));
s_vertices[3 * i + 2] = 0;
}
}
void updateVertexData1()
{
for (int j = 100; j < 200; j++) {
s_vertices[3 * j] = centerx + radius * (cos(j * (2 * PI / 100))) / 5;
s_vertices[3 * j + 1] = centery + radius * (sin(j * (2 * PI / 100))) / 5;
s_vertices[3 * j + 2] = 0;
}
}
void updateVBO() {
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(s_vertices), s_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GLuint renderingProgram;
GLuint vao[numVAOs];
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);
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)
{
if (action == GLFW_PRESS)
{
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_L:
novX *= -1;
break;
case GLFW_KEY_R:
radius += 0.01;
updateVertexData();
updateVertexData1();
updateVBO();
break;
}
}
}
void cursorPosCallback(GLFWwindow* window, double xPos, double yPos)
{
}
void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
}
void init() {
renderingProgram = createShaderProgram();
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(s_vertices), s_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void cleanUpScene()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(renderingProgram);
}
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(8.0);
glDrawArrays(GL_LINE_LOOP, 0, 99);
glDrawArrays(GL_LINE_LOOP, 100, 200);
if (currentTime - lastUpdate >= updateFrequency) {
centerx += novX;
centery += novY;
if (centerx + radius > 1 - abs(novX) || centerx - radius < -1 + abs(novX))
novX *= -1;
if (centery + radius > 1 - abs(novY) || centery - radius < -1 + abs(novY))
novY *= -1;
lastUpdate = currentTime;
updateVertexData();
updateVertexData1();
updateVBO();
}
glBindVertexArray(0);
}
int main(void) {
updateVertexData();
updateVertexData1();
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(600, 600, "VAO VBO", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
init();
lastUpdate = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
cleanUpScene();
glfwTerminate();
exit(EXIT_SUCCESS);
}
I use OpenGL 3.2, GLFW and GLEW. I try to render simple triangle using VAO and simple shader on OS X (10.8.2), but nothing shows, only white screen. Shaders compile ok, GLEW inits ok, glGetString(GL_VERSION) shows 3.2, tried to put glGetError after every line, it didn't report any errors. I don't know what i do wrong. Here's the code:
#include "include/GL/glew.h"
#include "include/GL/glfw.h"
#include <cstdlib>
#include <iostream>
GLuint program;
char *textFileRead(char *fn) {
FILE *fp;
char *content = NULL;
int count=0;
if (fn != NULL) {
fp = fopen(fn,"rt");
if (fp != NULL) {
fseek(fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);
if (count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
return content;
}
void checkCompilationStatus(GLuint s) {
GLint status = 0;
glGetShaderiv(s, GL_COMPILE_STATUS, &status);
if (status == 0) {
int infologLength = 0;
int charsWritten = 0;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &infologLength);
if (infologLength > 0)
{
GLchar* infoLog = (GLchar *)malloc(infologLength);
if (infoLog == NULL)
{
printf( "ERROR: Could not allocate InfoLog buffer");
exit(1);
}
glGetShaderInfoLog(s, infologLength, &charsWritten, infoLog);
printf( "Shader InfoLog:\n%s", infoLog );
free(infoLog);
}
}
}
void setShaders() {
GLuint v, f;
char *vs = NULL,*fs = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("minimal.vert");
fs = textFileRead("minimal.frag");
const char * vv = vs;
const char * ff = fs;
glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
free(vs);free(fs);
glCompileShader(v);
checkCompilationStatus(v);
glCompileShader(f);
checkCompilationStatus(f);
program = glCreateProgram();
glAttachShader(program,v);
glAttachShader(program,f);
GLuint error;
glLinkProgram(program);
glUseProgram(program);
}
int main(int argc, char* argv[]) {
glfwInit();
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwOpenWindow(800, 600, 8, 8, 8, 8, 24, 8, GLFW_WINDOW);
glViewport(0, 0, 800, 600);
glfwSetWindowTitle("Triangle");
glewExperimental = GL_TRUE;
GLenum result = glewInit();
if (result != GLEW_OK) {
std::cout << "Error: " << glewGetErrorString(result) << std::endl;
}
std::cout << "VENDOR: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "RENDERER: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "VERSION: " << glGetString(GL_VERSION) << std::endl;
std::cout << "GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
setShaders();
GLfloat vertices[] = {
1.0f, 1.0f, 0.f,
-1.f, -1.f, 0.f,
1.f, -1.f, 0.f
};
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint pos = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
glClearColor(1.0, 1.0, 1.0, 1.0);
while (glfwGetWindowParam(GLFW_OPENED)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers();
glfwSleep(0.001);
}
}
And here are the shaders, vertex shader:
#version 150
in vec3 position;
void main()
{
gl_Position = vec4(position, 0);
}
fragment shader:
#version 150
out vec4 out_color;
void main()
{
out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
The w parameter in your vertex shader should be set to 1, not 0.
gl_Position = vec4(position, 1)
For more information see the section titled "Normalized Coordinates" under "Rasterization Overview" on this page
... The X, Y, and Z of each vertex's position
is divided by W to get normalized device coordinates...
So your coordinates were being divided by 0. A number divided by 0 is undefined.