I try learing OpenGL with those two tutorials:
https://learnopengl.com/#!Getting-started/Hello-Triangle and
https://www.youtube.com/playlist?list=PLEETnX-uPtBXT9T-hD0Bj31DSnwio-ywh
When I draw a simple triangle it is only white. But the code seems right.
This is the fragment Shader:
#version 330 core
out vec4 fragColor;
void main()
{
fragColor = vec4(0.5, 0.3, 0.1, 1.0);
}
This is the ShaderProgram:
ShaderProgram::ShaderProgram(std::string fileName)
{
vertexShader = glCreateShader(GL_VERTEX_SHADER);
if (vertexShader == 0)
std::cerr << "VertexShader creation failed! " << std::endl;
const char* vertexShaderSource = (SourceLoader(fileName + ".vs")).c_str();
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
CheckErrorMessages(vertexShader, GL_COMPILE_STATUS, false, "VertexShader Compilation failed! ");
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
if (fragmentShader == 0)
std::cerr << "FragmentShader Creation failed! " << std::endl;
const char* fragmentShaderSource = (SourceLoader(fileName + ".fs")).c_str();
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
CheckErrorMessages(fragmentShader, GL_COMPILE_STATUS, false, "FragmentShader Compilation failed! ");
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
CheckErrorMessages(program, GL_LINK_STATUS, true, "Program linking failed! ");
glValidateProgram(program);
CheckErrorMessages(program, GL_VALIDATE_STATUS, true, "Program validation failed! ");
}
I have three methods in the ShaderProgram class:
1. a method to load the shader code, which is definitly working.
2. a method to Check for Error Messages, which is also working.
3. and a bind() Funktion which is just using glUseProgram(program)
I also have a class for the window, which is created by SDL
Display::Display(std::string title, unsigned int width, unsigned int height)
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_glcontext = SDL_GL_CreateContext(m_window);
GLenum status = glewInit();
if (status != GLEW_OK)
std::cerr << "GLEW failed to initialize!" << std::endl;
isClosed = false;
}
the Display class has a method to update and clear:
void Display::Update()
{
SDL_GL_SwapWindow(m_window);
SDL_Event e;
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
isClosed = true;
}
}
void Display::Clear(float red, float green, float blue, float alpha)
{
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
I also have a class called Mesh to manage VAO and VBO etc.:
Mesh::Mesh(Vertex* vertices, unsigned int numVertices)
{
drawCount = numVertices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*)0);
glEnableVertexAttribArray(0);
}
Mesh has one Funktion to draw the given vertices:
void Mesh::Draw()
{
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, drawCount);
glBindVertexArray(0);
}
The main Funktion consists out of a while loop:
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
Display display("Fenster", 1024, 840);
ShaderProgram shader("./res/Shader");
Vertex vertices[] = { Vertex(glm::vec3(1, 1, 0)), Vertex(glm::vec3(1, -1, 0)), Vertex(glm::vec3(-1, -1, 0)) };
Mesh mesh(vertices, 3);
while (!display.getIsClosed())
{
display.Clear(1.0f, 0.0f, 1.0f, 1.0f);
shader.Bind();
mesh.Draw();
display.Update();
}
SDL_Quit();
return 0;
}
The problem is I don´t get any Error, but the triangle keep staying white.
Thank you for helping!
Edit: Vertex Shader is here:
#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
If you check your infoLog you'd find that your shaders aren't compiling. You're assigning the shader source pointer to a temporary string that gets destroyed at the end of the line, and you're sending gibberish to the shader compiler:
const char* fragmentShaderSource = (SourceLoader(fileName + ".fs")).c_str();// After this line the pointer isn't valid
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
SourceLoader returns a temporary string, and you assign fragmentShaderSource pointer to the string. Then there is junk data there by the time you pass it to glShaderSource. You can do:
std::string vertShaderString = SourceLoader(fileName + ".vs");
const char* vertShaderSource = vertShaderString.c_str();
glShaderSource(vertexShader, 1, &vertShaderSource, NULL);
You also need to fix the same problem for the fragment shader.
Also you drew a clockwise winding triangle, which is fine, but by default OpenGL considers counterclockwise winding as front-facing.
Another thing, the reason you didn't catch the error is because you CheckErrorMessages doesn't do anything, you should be writing the infoLog to the string or something.
Related
Both the vertex and fragment shader seem to be compiling and the window appears and is given the clear color but I cannot get the triangle to render. I have tried to just use the glBegin(); vertex(); glEnd(); as an alternative but this also resulted in no rendered triangle.
main.c
#include <stdio.h>
#include <unistd.h>
#include <gfx/shader.h>
#include <gfx/vbo.h>
#include <gfx/vao.h>
GLfloat vertices[] = {
0.0f,1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,-1.0f,0.0f
};
int main(void){
if(!glfwInit()){
fprintf(stderr, "Unable to init GLFW.\n");
exit(1);
}
GLFWwindow *win;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
win = glfwCreateWindow(SCREENWIDTH, SCREENHEIGHT, "Terraria", NULL, NULL);
if(win==NULL){
fprintf(stderr, "Error creating opengl window\n");
glfwTerminate();
exit(1);
}
glfwMakeContextCurrent(win);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
fprintf(stderr, "Unable to init glad\n");
glfwTerminate();
exit(1);
}
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(win, frame_buffer_size_cb);
struct Shader s = create_shader("resources/shaders/vec2.vs", "resources/shaders/vec2.fs");
uint32_t vaoID, vboID;
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(vboID, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
while(!glfwWindowShouldClose(win)){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(s.sh);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
3*sizeof(GLfloat),
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0,3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(win);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
shader.h
#include <gfx/gfx.h>
struct Shader{
uint32_t sh;
uint32_t vsh;
uint32_t fsh;
};
struct Shader create_shader(const char *vs_path, const char *fs_path);
shader.c
#include <gfx/shader.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
static uint32_t _compile(int8_t id, const char *path, uint16_t type){
uint32_t sh; //Shader handle or ID
FILE *fp = fopen(path, "rb"); //Open the shader source code file
long sz = file_size(fp); //Get the file size
char *shaderSource; //Create object to holder shader source code
shaderSource = calloc(sz+1, 1);
fread(shaderSource, 1, sz, fp); //Read the shader source code into new buffer
fclose(fp);
assert(strlen(shaderSource)>0);
sh = glCreateShader(type);
glShaderSource(sh, 1, (const GLchar **)&shaderSource, NULL);
glCompileShader(sh);
int success;
char infoLog[512];
glGetShaderiv(sh, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(sh, 512, NULL, infoLog);
printf("Unable to compile shader id %d\n", id);
}
free(shaderSource);
return sh;
}
struct Shader create_shader(const char *vs_path, const char *fs_path){
struct Shader h;
h.vsh = _compile(1,vs_path, GL_VERTEX_SHADER);
h.fsh = _compile(0,fs_path, GL_FRAGMENT_SHADER);
h.sh = glCreateProgram();
glAttachShader(h.sh, h.vsh);
glAttachShader(h.sh, h.fsh);
glLinkProgram(h.sh);
// check for linking errors
int success;
char infoLog[512];
glGetProgramiv(h.sh, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(h.sh, 512, NULL, infoLog);
printf("Unable to link gl program\n");
}
glDetachShader(h.sh, h.vsh);
glDetachShader(h.sh, h.fsh);
glDeleteShader(h.vsh);
glDeleteShader(h.fsh);
return h;
}
vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
void main(){
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
fragment shader
#version 330 core
out vec4 FragColor;
void main(){
FragColor = vec4(1.0,1.0,1.0,1.0);
}
I have found the answer. If you look really closely in main, it seems that you are actually supposed to call glBindBuffer to the macro GL_ARRAY_BUFFER and not to the vbo handle like I thought. Fixing this caused my program to function. Also my window hints were not taking effect because I was calling them after creating the window.
I was trying to draw with coordinates being of integer type, but failed. Then I tried to draw a simple triangle as if from tutorial. In the result half of the screen was of triangle's color, other was glClearColor I set. I started changing values, and corners started to show up when coordinates were smaller than 0.00000000000000000005f (which i suspect would be of higher precision than a float), though should have been already with smaller than 1.0f. Trying to search didn't have any results, perhaps because I don't know the right words.
Here's code I ended up with:
Includes and function I quickly moved here:
#include <GL/glew.h>
#include <glfw3.h>
#include <unistd.h>
#include <stdio.h>
/* function that creates shader */
GLuint makeShader(const GLchar* vertexShaderSource, const GLchar* fragmentShaderSource,
GLchar*& infoLog, const GLchar* geometryShaderSource = NULL)
{
GLint isSuccess;
infoLog = nullptr;
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShaderID);
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &isSuccess);
if(!isSuccess)
{
infoLog = new GLchar[1024];
glGetShaderInfoLog(vertexShaderID, 1024, nullptr, infoLog);
printf("Error compiling vertex shader: %s\n", infoLog);
printf("\n%s\n\n", vertexShaderSource);
return 0;
}
GLuint geometryShaderID;
if(geometryShaderSource!=NULL){
geometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometryShaderID, 1, &geometryShaderSource, nullptr);
glCompileShader(geometryShaderID);
glGetShaderiv(geometryShaderID, GL_COMPILE_STATUS, &isSuccess);
if(!isSuccess)
{
infoLog = new GLchar[1024];
glGetShaderInfoLog(geometryShaderID, 1024, nullptr, infoLog);
printf("Error compiling geometry shader: %s\n", infoLog);
printf("\n%s\n\n", geometryShaderSource);
return 0;
}
}
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShaderID);
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &isSuccess);
if(!isSuccess)
{
infoLog = new GLchar[1024];
glGetShaderInfoLog(fragmentShaderID, 1024, nullptr, infoLog);
printf("Error compiling fragment shader: %s\n", infoLog);
printf("\n%s\n\n", fragmentShaderSource);
return 0;
}
GLuint shaderID = glCreateProgram();
glAttachShader(shaderID, vertexShaderID);
glAttachShader(shaderID, fragmentShaderID);
if(geometryShaderSource!=NULL){
glAttachShader(shaderID, geometryShaderID);
}
glLinkProgram (shaderID);
glValidateProgram(shaderID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
if(geometryShaderSource!=NULL){
glDeleteShader(geometryShaderID);
}
glGetProgramiv(shaderID, GL_LINK_STATUS, &isSuccess);
if (!isSuccess)
{
infoLog = new GLchar[1024];
glGetProgramInfoLog(shaderID, 1024, nullptr, infoLog); // Generate error as infoLog
//std::cout << "Error " << infoLog << std::endl; // Display
printf("Error linking shader %s\n", infoLog);
return 0;
}
return shaderID;
}
Main:
int main(void)
{
GLFWwindow* window;
float FPSlimit = 60;
int windowSX = 800, windowSY = 600;
/* Initialize the library */
if (!glfwInit()){
return -1;}
/* Create window */
window = glfwCreateWindow(windowSX, windowSY, "abc", NULL, NULL);
if (!window)
{
printf("Failed to create window\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
/* Initialize GLEW */
if(glewInit()){
printf("Failed to initialize GLEW\n");
glfwTerminate();
return -1;
}
glClearColor(0.1, 0.3f, 0.2f, 1.0f);
double timeDeltaFPSmaintain = 0;
GLuint vao;
GLuint vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
//changing normalisation to GL_TRUE didnt do anything
float dat[] = {-0.000000000000000000024f, -0.000000000000000000024f, 0.f,
1.f, -1.f, 0.f,
0.f, 0.000000000000000000054f, 0.f};
glBufferData(GL_ARRAY_BUFFER, 3*3*sizeof(float), dat, GL_STATIC_DRAW);
GLchar* log;
const GLchar* v = "#version 330 \n layout (location = 0) in vec3 pos;\n void main(){gl_Position = vec4(pos.xyz, 0);}";
const GLchar* f = "#version 330 \n out vec4 color; void main(){color = vec4(1, 0, 0, 0);}";
GLuint sha = makeShader(v, f, log);
printf("%i\n", glGetError());//Shows 0
/* Main loop: */
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(sha);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
// nvidia starts to use 100% of one of CPU cores with vSync for some reason
timeDeltaFPSmaintain = (glfwGetTime() - timeDeltaFPSmaintain)*1000000;
if(FPSlimit>1){
usleep(1000000/FPSlimit-unsigned(timeDeltaFPSmaintain));}
timeDeltaFPSmaintain = glfwGetTime();
}
glfwTerminate();
return 0;
}
Compiler also tells me about corrupt .drective at the end of def file but I doubt it matters much.
The transformation in your vertex shader is just broken:
gl_Position = vec4(pos.xyz, 0);
Setting w_clip = 0 will mean that conceptually, your points are infinitly far away into the direction of x,y,z, and the GPU will clip your primitive to the intersection with the viewing volume (which still is finite).
Also:
I started changing values, and corners started to show up when coordinates were smaller than 0.00000000000000000005f (which i suspect would be of higher precision than a float),
That's not how floating point numbers work, the precision approaching zero is quite high, the smallest non-denormalized single precision floating point number will be 2^(-126), which is approximately 0.000000000000000000000000000000000000012, and you can get down to 2^-149 if you go into the de-normalized range.
Hey there Im trying to draw a simple quad with 2 triangles in OpenGL through a vbo.
However I have looked at my code multiple times and I don't see what I am missing.
I ain't no Open GL expert, The code was working fine without any buffers however when I switchted to VBO Im not seeing anything anymore. OpenGL also doesn't provide any helpfull errors.
Image::Image(Graphics * GFX)
{
glm::vec2 corners[2];
corners[0] = glm::vec2(0, 0);
corners[1] = glm::vec2(1, 1);
vertices = new GLfloat[30]
{
//Vertices XYZ TexCoord X,Y
corners[0].x, corners[0].y, 0.0f, 0,0,
corners[0].x, corners[1].y, 0.0f, 0,1,
corners[1].x, corners[0].y, 0.0f, 1,0,
corners[1].x,corners[1].y,0.0f, 1,1,
corners[0].x, corners[1].y,0.0f, 0,1,
corners[1].x, corners[0].y, 0.0f, 1,0
};
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//Setting up some stuff
const char *vertexShaderSource =
"attribute vec4 vPosition; \n"
"attribute vec2 vTexCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char *fragmentShaderSource =
"precision mediump float; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"
"} \n";
// Load and compile the vertex/fragment shaders
vertexShader = GFX->LoadShader(GL_VERTEX_SHADER, (const char*)vertexShaderSource);
fragmentShader = GFX->LoadShader(GL_FRAGMENT_SHADER, (const char*)fragmentShaderSource);
// Create the program object
programObject = glCreateProgram();
// now we have the V and F shaders attach them to the progam object
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
// Link the program
glLinkProgram(programObject);
// Check the link status
// Link the program
GLint AreTheylinked;
glGetProgramiv(programObject, GL_LINK_STATUS, &AreTheylinked);
if (!AreTheylinked)
{
GLint RetinfoLen = 0;
// check and report any errors
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &RetinfoLen);
if (RetinfoLen > 1)
{
GLchar* infoLog = (GLchar*)malloc(sizeof(char) * RetinfoLen);
glGetProgramInfoLog(programObject, RetinfoLen, NULL, infoLog);
fprintf(stderr, "Error linking program:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
}
positionLocation = glGetAttribLocation(programObject, "vPosition");
textureCoordLocation = glGetAttribLocation(programObject, "vTexCoord");
if (glGetError() == GL_NO_ERROR) {}
else
printf("Init failed!\n");
//End setting up
}
Image::~Image()
{
}
void Image::Draw()
{
std::cout << "Calling Draw on Image" << std::endl;
glUseProgram(programObject);
glEnable(GL_DEPTH_TEST);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLsizei stride = (5) * sizeof(GLfloat);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
if (glGetError() != GL_NO_ERROR)
{
printf("UI Draw error\n");
}
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
And how I am loading the shaders:
GLuint Graphics::LoadShader(GLenum type, const char *shaderSrc)
{
// 1st create the shader object
GLuint TheShader = glCreateShader(type);
if (TheShader == 0) return FALSE; // can't allocate so stop.
// pass the shader source then compile it
glShaderSource(TheShader, 1, &shaderSrc, NULL);
glCompileShader(TheShader);
GLint IsItCompiled;
// After the compile we need to check the status and report any errors
glGetShaderiv(TheShader, GL_COMPILE_STATUS, &IsItCompiled);
if (!IsItCompiled)
{
GLint RetinfoLen = 0;
glGetShaderiv(TheShader, GL_INFO_LOG_LENGTH, &RetinfoLen);
if (RetinfoLen > 1)
{ // standard output for errors
char* infoLog = (char*)malloc(sizeof(char) * RetinfoLen);
glGetShaderInfoLog(TheShader, RetinfoLen, NULL, infoLog);
fprintf(stderr, "Error compiling this shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(TheShader);
return FALSE;
}
return TheShader;
}
It worked fine without a buffer previously, and saw a white square by using:
glVertexAttribPointer(0, 6, GL_FLOAT, GL_FALSE, 0, vertices);
But now I want to add texture coordinates to my quad through a VBO but nothing shows anymore.
Smoothy101
Your buffer creation looks fine - the problem is your attribute pointer setup. You've added texture coordinates which has changed data layout for each vertex, but you've not handled that in your code.
You need something like this:
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(textureCoordLocation, 2, GL_FLOAT, GL_FALSE, stride, 8);
... not this:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
Searched Stack Overflow for similar questions in search of my solution , but it doesn't seem to be solved.
main.cpp :
#include"reader.h"
#include"window.h"
#include"shader.h"
int main() {
float vertices[] = {
-0.5f, -0.5f, 0.0f ,
0.5f, -0.5f, 0.0f ,
0.0f, 0.5f, 0.0f
};
Window window;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Shader shader;
shader.addShader("./src/shaders/basic.vtx",GL_VERTEX_SHADER);
shader.addShader("./src/shaders/basic.frg", GL_FRAGMENT_SHADER);
shader.compile();
shader.enable();
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,GL_STATIC_DRAW);
GLint pos_in = glGetAttribLocation(shader.getProgram(), "pos_in");
if (pos_in < 0) {
std::cout << "pos_in not found\n";
}
glVertexAttribPointer(pos_in, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(pos_in);
while (!window.closed()) {
window.update();
glDrawArrays(GL_TRIANGLES,0,3);
}
return 0;
}
shader.h :
#pragma once
#include<glad/glad.h>
#include<iostream>
#include<vector>
#include"reader.h"
class Shader {
std::vector<GLuint*> shaders;
GLuint program;
public :
GLuint& getProgram() {
return program;
}
Shader() {
program = glCreateProgram();
}
void addShader(const char * path, GLenum type) {
std::string data = ShaderReader(path).read_shader();
const char * chardata = data.c_str();
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &chardata , nullptr);
glCompileShader(shader);
int success;
char buffer[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(shader, 512, NULL, buffer);
std::cout << buffer << std::endl;
return;
}
std::cout << "shader inserted into vector\n";
shaders.push_back(&shader);
}
void compile(){
for (int i = 0; i != shaders.size();i++) {
glAttachShader(program, *shaders[i]);
}
glLinkProgram(program);
glValidateProgram(program);
glUseProgram(program);
int status;
glGetProgramiv(program, GL_COMPILE_STATUS, &status);
char buffer[512];
if (!status) {
glGetProgramInfoLog(program,512,NULL,buffer);
std::cout << buffer << std::endl;
return;
}
std::cout << "shader compilation successful\n";
}
void enable() {
glUseProgram(program);
}
void disable() {
glUseProgram(0);
}
~Shader() {
for (int i = 0; i != shaders.size();i++) {
glDeleteShader(*shaders[i]);
}
}
};
vertex shader written in basic.vtx:
#version 400
layout (location = 0 ) in vec3 pos_in ;
void main(){
gl_Position = vec4(pos_in.x , pos_in.y , pos_in.z , 1.0f);
}
fragment shader written in basic.frg :
#version 400
out vec4 color;
void main(){
color = vec4(0.0f, 0.5f , 0.5f , 1.0f);
}
At the time of calling glGetAttribLocation , the vertex shader IS USING pos_in attrib to set gl_Position , yet it returns -1 .
Also the triangle is not rendered when calling glGetAttribLocation() ; or rendered white with direct attrib pointer values like 0 , 1 with an openGL 1281 error.
One thing that is definitely not valid is the shaders.push_back(&shader):
void addShader(const char * path, GLenum type) {
// ....
GLuint shader = glCreateShader(type);
// ....
shaders.push_back(&shader);
}
With the shaders.push_back(&shader) you push back the address of a local variable to the shaders vector. So the glAttachShader(program, *shaders[i]); will result in undefined behavior.
shader holds only an numeric id so there is no need to get a pointer to that, just change the std::vector<GLuint*> shaders to std::vector<GLuint> shaders, use shaders.push_back(shader) and replace all *shaders[i] with shaders[i]
The reason why you don't get an linking error is most likely because the content at the address you get from &shader is not overwritten before you do the glAttachShader(program, *shaders[i]), and that both entries in the shaders vector hold same address of the stack. The result of is that glAttachShader is called each time on the same id, so you bind only the fragement shader to the program.
I am getting an error when trying to use VAO's inside of SFML and not sure if it is SFML or it is my own opengl code
GLenum err = glewInit();
if (err != GLEW_OK)
{
std::cout << "NOT WORKING" << std::endl;
}
std::vector<sf::Vector3f> g_vertext_buffer_data;
g_vertex_buffer_data.push_back({ -1.0f, -1.0f, 0.0f });
g_vertex_buffer_data.push_back({1.0f, -1.0f, 0.0f});
g_vertex_buffer_data.push_back({ 0.0f, 1.0f, 0.0f });
const char* vertexShaderSource =
"#version 330\n\
in vec4 position;\
void main(void){\ gl_Position = position;\
}";
// compile fragment shader source
const GLchar* fragmentShaderSource =
"#version 330\n\
void main(void) {\
out vec4 fragcolor; fragcolor= vec4(1.0,1.0,1.0,1.0);\
}";
/* Creating Shader */
this->programId = glCreateProgram();
this->vId = glCreateShader(GL_VERTEX_SHADER);
this->fId = glCreateShader(GL_FRAGMENT_SHADER);
/* Get Shader Size */
int vertexShaderLength = strlen(vertexShaderSource);
int fragmentShaderLength = strlen(fragmentShaderSource);
/* Loading and binding shader */
glShaderSource(this->vId, 1, &vertexShaderSource, NULL);
glShaderSource(this->fId, 1, &fragmentShaderSource, NULL);
/* Compile Shaders */
glCompileShader(vId);
glCompileShader(fId);
/* Attach Shaders */
glAttachShader(this->programId, this->vId);
glAttachShader(this->programId, this->fId);
/* Linkg program */
glLinkProgram(this->programId);
/* Use and bind attribute */
glUseProgram(this->programId);
this->positionId = glGetAttribLocation(this->programId, "position");
glUseProgram(0);
/* VAO Time */
glGenVertexArrays(1, &this->vaoId);
glBindVertexArray(this->vaoId);
/* VBO Time assigning to VAO */
glGenBuffers(1, &this->vboId);
glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
glBufferData(GL_ARRAY_BUFFER, g_vertex_buffer_data.size() * sizeof(sf::Vector3f), &g_vertex_buffer_data[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(this->positionId);
glVertexAttribPointer(this->positionId, 2, GL_FLOAT, GL_FALSE, sizeof(sf::Vector3f), 0);
/* Close out bindings */
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while(1)
{
glUseProgram(this->programId);
glBindVertexArray(this->vaoId);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
gameWindow.glPushStates();
}
The error code I get is: opengl error in user code (1282)
I have changed the size() issue that was brought up in the blBufferData() but still am getting the issue.
There is at least a problem with the size that is passed to glBufferData:
glBufferData(GL_ARRAY_BUFFER,
sizeof(g_vertex_buffer_data) * sizeof(sf::Vector3f),
g_vertex_buffer_data[0], GL_STATIC_DRAW);
sizeof(g_vertex_buffer_data) is equal to sizeof(std::vector<?>) which is the size of the vector object and not the size of the data contained. Try using
glBufferData(GL_ARRAY_BUFFER,
g_vertex_buffer_data.size() * sizeof(sf::Vector3f),
g_vertex_buffer_data[0], GL_STATIC_DRAW);
Another thing: In OpenGL 3.3 Core Profile there is no gl_FragColor variable. You will have to define an out variable.
Next: Your vertex shader seems to be empty. You have to write to gl_Position otherwise nothing will be shown.
Possible error codes for glGetAttribLocation are:
GL_INVALID_OPERATION
Which don't have a fixed value. Try to get the error string with gluErrorString() or take a look in the header to which of those 1282 maps.
• check your shader got compiled without error?
• check your shader got linked without error?
What type have positionId? All object id's must be GLuint type.
And btw allways enable shader compilation-linking error check, and debug will be more informative.
I do that in this way (OpenGL-ES 2.0):
m_nVertexShader = glCreateShader(GL_VERTEX_SHADER);
m_nPixelShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(m_nVertexShader, 1, &lpszVertexBuffer, NULL);
glShaderSource(m_nPixelShader, 1, &lpszFragmentBuffer, NULL);
glCompileShader(m_nVertexShader);
int iIsOk = 0;
glGetShaderiv(m_nVertexShader, GL_COMPILE_STATUS, &iIsOk);
if(!iIsOk)
{
GLint infoLen = 0;
glGetShaderiv(m_nVertexShader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(m_nVertexShader, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteShader(m_nVertexShader);
return;
}
glCompileShader(m_nPixelShader);
glGetShaderiv(m_nPixelShader, GL_COMPILE_STATUS, &iIsOk);
if(!iIsOk)
{
GLint infoLen = 0;
glGetShaderiv(m_nPixelShader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(m_nPixelShader, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteShader(m_nPixelShader);
return;
}
m_nProgram = glCreateProgram();
glAttachShader(m_nProgram, m_nVertexShader);
glAttachShader(m_nProgram, m_nPixelShader);
glBindAttribLocation(m_nProgram, 0, "rm_Vertex");
glLinkProgram(m_nProgram);
glGetProgramiv(m_nProgram, GL_LINK_STATUS, &iIsOk);
// Fail to pass status validation
if(!iIsOk)
{
GLint infoLen = 0;
glGetProgramiv(m_nProgram, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(m_nProgram, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteProgram(m_nProgram);
return;
}
glUseProgram(m_nProgram);
As you use GLSL 3.3, fist you must specify fragment rendertarget output by calling
glBindFragDataLocation(this->programId, 0, "fragcolor");
Secondly your fragment shader must be like
"#version 330
out vec4 fragcolor;
void main(void) {
fragcolor= vec4(1.0,1.0,1.0,1.0);
}
The example of using this kind of shaders is on OpenGL 3.3 + GLSL 1.5 Sample.