I am just getting started with OpenGL, and have already hit a pretty frustrating bug with it. I've followed the learnopengl tutorial, encapsulating most stuff into a renderer class, which has uints for buffers and such. Here is the main code that does everything:
#include <gfx/gfx.h>
#include <gfx/gl.h>
#include <gfx/shaders.h>
#include <iostream>
void Renderer::init() {
vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
glCompileShader(vertex_shader_id);
GLint vertex_shader_status;
glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &vertex_shader_status);
if (vertex_shader_status == false) {
std::cout << "vsh compilation failed due to";
char vertex_fail_info_log[1024];
glGetShaderInfoLog(vertex_shader_id, 1024, nullptr, vertex_fail_info_log);
std::cout << vertex_fail_info_log << std::endl;
abort();
}
fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
glCompileShader(fragment_shader_id);
GLint fragment_shader_status;
glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &fragment_shader_status);
if (fragment_shader_status == false) {
std::cout << "fsh compilation failed due to";
char fragment_fail_info_log[1024];
glGetShaderInfoLog(fragment_shader_id, 1024, nullptr, fragment_fail_info_log);
std::cout << fragment_fail_info_log << std::endl;
abort();
}
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader_id);
glAttachShader(shader_program, fragment_shader_id);
glLinkProgram(shader_program);
GLint shader_program_status;
glGetProgramiv(shader_program, GL_LINK_STATUS, &shader_program_status);
if (shader_program_status == false) {
std::cout << "shprogram compilation failed due to";
char shader_program_fail_info_log[1024];
glGetShaderInfoLog(shader_program, 1024, nullptr, shader_program_fail_info_log);
std::cout << shader_program_fail_info_log << std::endl;
abort();
}
glUseProgram(shader_program);
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
}
void Renderer::draw(f32 verts[]) {
glUseProgram(shader_program);
glClearColor(1, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glCreateVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(vertex_array);
glUseProgram(shader_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Here is shaders.h :
#ifndef SHADERS_H
#define SHADERS_H
const char* vertex_shader =
"#version 460 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main() {\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n\0";
const char* fragment_shader =
"#version 460 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
"FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";
#endif
I cannot figure out for life of me, what is wrong. The red clear color shows up, but nothing else.
Looks like there's a problem with your draw method. The signature is void Renderer::draw(f32 verts[]) { Then later on you call glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); . The thing is, when you pass an array to a function, it decays to a pointer (Even though the declaration can make that look like it's not happening, which is very confusing). So in a function parameter, draw(f32 verts[]) is equivalent to draw(f32* verts). This question has some explanations on what's happening there.
Anyways, when you call sizeof(verts), you're just getting the number of bytes of a float pointer, not the number of bytes owned by verts. So you will not be specifying enough bytes when you call glBufferData() to create the triangle you are going for. The simple fix is to pass a length into your draw function, and then you would have something like
void Renderer::draw(f32* verts, int length) {
//...
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * length, verts, GL_STATIC_DRAW);
//...
}
Here is some docs on this particular function. It is possible there are other errors, but since you aren't blackscreening, and generally the code looks right, it is unlikely there's a bunch of invalid operations or anything.
To continue debugging after this, add the following to your code
#define GL_ERROR_CHECK() (log_error(__FILE__, __LINE__))
void log_error(const* file, int line) {
GLenum err;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "GL error " << err << " in " << file << "at line " << line << std::endl;
}
}
and sprinkle GL_ERROR_CHECK() all over the place to see if any of the OpenGL calls were invalid.
Related
I'm jumping through the hoops right now to learn opengl and I've come across an issue. On my desktop computer with a nvidia gtx 780 opengl is printing out a warning via the glDebugMessageCallback mechanism:
"Buffer object 1 (bound to _GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations."
I'm rendering 1 cube with a vertex and index buffer so this message repeats for every buffer object I'm creating (2 of them). However, there is also one final warning at the end which states:
"Vertex shader in program 3 is being recompiled based on GL State."
I'm still able to render my cube I was rendering before, but the color I had set is flashing between white and the color now. I searched online and found this answer - https://community.khronos.org/t/nvidia-output-debug-error-131185/66033 - which basically said this is nothing but a warning and everything should be fine but that wouldn't explain why my cube is flashing between white and my color now. This same code is working fine on my laptop (2019 Asus laptop which also has a nvidia GTX graphics chip). Anyone come across this issue before? Here is the relevant code:
const char* vertexShaderCode =
R"HereDoc(
#version 430
in layout(location=0) vec3 position;
in layout(location=1) vec3 color;
out vec3 fragColor;
uniform mat4 transformationMatrix;
void main()
{
vec4 newPos = vec4(position, 1.0) * transformationMatrix;//vector is on the left side because my matrices are row major
gl_Position = newPos;
vec3 changedColors;
changedColors.r += color.r + 0;
changedColors.g += color.g + 0;
changedColors.b += color.b + 0;
fragColor = changedColors;
};
)HereDoc";
const char* fragmentShaderCode =
R"HereDoc(
#version 430
out vec4 color;
in vec3 fragColor;
void main()
{
color = vec4(fragColor, 1.0f);
};
)HereDoc";
void GLAPIENTRY MyOpenGLErrorCallbackFunc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
{
BGZ_CONSOLE("%s type=0x%x %s\n", ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), type, message);
};
void CheckCompileStatus(GLuint shaderID)
{
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if(compileStatus != GL_TRUE)
{
GLint infoLogLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar buffer[512] = {};
GLsizei bufferSize;
glGetShaderInfoLog(shaderID, infoLogLength, &bufferSize, buffer);
BGZ_CONSOLE("%s", buffer);
InvalidCodePath;
};
};
void CheckLinkStatus(GLuint programID)
{
GLint linkStatus;
glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus);
if(linkStatus != GL_TRUE)
{
GLint infoLogLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar buffer[512] = {};
GLsizei bufferSize;
glGetProgramInfoLog(programID, infoLogLength, &bufferSize, buffer);
BGZ_CONSOLE("%s", buffer);
InvalidCodePath;
};
};
local_func void InstallShaders()
{
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const char* adapter[1];
adapter[0] = vertexShaderCode;
glShaderSource(vertexShaderID, 1, adapter, 0);
adapter[0] = fragmentShaderCode;
glShaderSource(fragmentShaderID, 1, adapter, 0);
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
CheckCompileStatus(vertexShaderID);
CheckCompileStatus(fragmentShaderID);
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
CheckLinkStatus(programID);
glUseProgram(programID);
};
local_func void
GLInit(int windowWidth, int windowHeight)
{
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(MyOpenGLErrorCallbackFunc, 0);
glViewport(0, 0, windowWidth, windowHeight);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);//Defaults to CCW ordering of indicies meaning all indicies that, from the viewers perspective, creating triangles in a CW manner repsrent visible triangles.
glCullFace(GL_BACK);//Culls only back faces (faces facing away from viewer)
InstallShaders();
}
void Draw(Memory_Partition* memPart, s32 id, RunTimeArr<s16> meshIndicies)
{
glDisable(GL_TEXTURE_2D);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2);
glDrawElements(GL_TRIANGLES, (s32)meshIndicies.length, GL_UNSIGNED_SHORT, 0);
glEnable(GL_TEXTURE_2D);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
};
//This implements a discriminated union for buffering render commands that my game code layer uses.
void RenderViaHardware(Rendering_Info&& renderingInfo, Memory_Partition* platformMemoryPart, int windowWidth, int windowHeight)
{
local_persist bool glIsInitialized { false };
if (NOT glIsInitialized)
{
GLInit(windowWidth, windowHeight);
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glIsInitialized = true;
};
u8* currentRenderBufferEntry = renderingInfo.cmdBuffer.baseAddress;
Camera3D camera3d = renderingInfo.camera3d;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
for (s32 entryNumber = 0; entryNumber < renderingInfo.cmdBuffer.entryCount; ++entryNumber)
{
RenderEntry_Header* entryHeader = (RenderEntry_Header*)currentRenderBufferEntry;
switch (entryHeader->type)
{
case EntryType_InitBuffer:{
RenderEntry_InitBuffer bufferData = *(RenderEntry_InitBuffer*)currentRenderBufferEntry;
ScopedMemory scope{platformMemoryPart};
RunTimeArr<GLfloat> verts{};
InitArr(verts, platformMemoryPart, bufferData.verts.length * 6);
s32 i{};
f32 colorR{1.0f}, colorG{}, colorB{};//Im just hard coding color data right now while I'm learning
for(s32 j{}; j < bufferData.verts.length; ++j)
{
verts.Push(bufferData.verts[j].x);
verts.Push(bufferData.verts[j].y);
verts.Push(bufferData.verts[j].z);
verts.Push(colorR);
verts.Push(colorG);
verts.Push(colorB);
};
u32 vertexArrayID{};
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
GLuint bufferID;
glGenBuffers(1, &bufferID);
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * verts.length, verts.elements, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (char*)(sizeof(GLfloat)*3));
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s16) * bufferData.indicies.length, bufferData.indicies.elements, GL_DYNAMIC_DRAW);
currentRenderBufferEntry += sizeof(RenderEntry_InitBuffer);
}break;
//...other cases for entries which are irrelevant to problem
case EntryType_Geometry: {
ScopedMemory scope{platformMemoryPart};
RenderEntry_Geometry geometryEntry = *(RenderEntry_Geometry*)currentRenderBufferEntry;
//camera transform setup
Mat4x4 xRotMatrix = XRotation(camera3d.rotation.x);
Mat4x4 yRotMatrix = YRotation(camera3d.rotation.y);
Mat4x4 zRotMatrix = ZRotation(camera3d.rotation.z);
Mat4x4 fullRotMatrix = xRotMatrix * yRotMatrix * zRotMatrix;
v3 xAxis = GetColumn(fullRotMatrix, 0);
v3 yAxis = GetColumn(fullRotMatrix, 1);
v3 zAxis = GetColumn(fullRotMatrix, 2);
//Setup full transform matrix
Mat4x4 camTransform = ProduceCameraTransformMatrix(xAxis, yAxis, zAxis, camera3d.worldPos);
Mat4x4 projectionTransform = ProduceProjectionTransformMatrix_UsingFOV(renderingInfo.fov, renderingInfo.aspectRatio, renderingInfo.nearPlane, renderingInfo.farPlane);
Mat4x4 fullTransformMatrix = projectionTransform * camTransform * geometryEntry.worldTransform;
//Send transform matrix to vertex shader
GLint transformMatrixUniformLocation = glGetUniformLocation(3, "transformationMatrix");
glUniformMatrix4fv(transformMatrixUniformLocation, 1, GL_FALSE, &fullTransformMatrix.elem[0][0]);
Draw(platformMemoryPart, geometryEntry.id, geometryEntry.indicies);
currentRenderBufferEntry += sizeof(RenderEntry_Geometry);
}break;
InvalidDefaultCase;
};
}
renderingInfo.cmdBuffer.entryCount = 0;
};
EDIT:
I figured out the issue with the colors not working which was answered in the comments below. However, I still don't know what these warnings are trying to tell me and if they are anything I should be looking to fix.
You variable vec3 changedColors; is uninitialized. Initialize it with vec3 changedColors = vec3(0);. The reason why it works on your laptop might be that its graphics driver will initialize it to zero by default, while your other graphics driver won't.
Regarding the warning (not error). It just warns you that your buffer will be put in video memory since you're using GL_STATIC_DRAW for your buffer. It's actually more of a log and you can safely ignore it. If you want to get rid of it you have to filter it away in your callback (which you passed to glDebugMessageCallback). Your callback will have a severity parameter that lets you to filter messages with a certain severity.
Or, if you only want to get rid of that specific message, filter on its id value.
Here's an example taken from blog.nobel-joergensen.com:
void APIENTRY openglCallbackFunction(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
cout << "---------------------opengl-callback-start------------" << endl;
cout << "message: "<< message << endl;
cout << "type: ";
switch (type) {
case GL_DEBUG_TYPE_ERROR:
cout << "ERROR";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
cout << "DEPRECATED_BEHAVIOR";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
cout << "UNDEFINED_BEHAVIOR";
break;
case GL_DEBUG_TYPE_PORTABILITY:
cout << "PORTABILITY";
break;
case GL_DEBUG_TYPE_PERFORMANCE:
cout << "PERFORMANCE";
break;
case GL_DEBUG_TYPE_OTHER:
cout << "OTHER";
break;
}
cout << endl;
cout << "id: " << id << endl;
cout << "severity: ";
switch (severity){
case GL_DEBUG_SEVERITY_LOW:
cout << "LOW";
break;
case GL_DEBUG_SEVERITY_MEDIUM:
cout << "MEDIUM";
break;
case GL_DEBUG_SEVERITY_HIGH:
cout << "HIGH";
break;
}
cout << endl;
cout << "---------------------opengl-callback-end--------------" << endl;
}
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);
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I'm trying to draw a red triangle in OpenGL using GLEW. Firstly, I have drawn a triangle at the center of screen. This is getting drawn correctly. Then, I am trying to use shaders to get a red triangle. But, I couldn't get a red triangle because my shader compilation is failing. What could be possibly wrong?
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
std::cout << "failed to compile shader" << std::endl;
}
return id;
}
static int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int 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);
glDetachShader(program,vs);
glDetachShader(program,fs);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
std::cout << "error..!!" << std::endl;
}
float positions[6] = {
-0.5f,-0.5f,
0.5f, -0.5f,
0.0f, 0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float),positions,GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
std::string vertexShader =
"#version 330 core\n"
"\n"
"layout(location=0) in vec4 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position=position;\n"
"}\n";
std::string fragmentShader =
"#version 330 core\n"
"\n"
"layout(location=0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color=vec4(1.0,0.0,0.0,1.0)\n"
"}\n";
unsigned int shader = CreateShader(vertexShader,fragmentShader);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
The shader compilation fails, because shader there is missing a semicolon after color=vec4(1.0,0.0,0.0,1.0) in the fragment.
If you print the shader info log, then you can find issues like this easily:
glCompileShader(id);
GLint status;
glGetShaderiv( id, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )
{
GLint maxLen;
glGetShaderiv( id, GL_INFO_LOG_LENGTH, &maxLen );
std::vector< char >log( maxLen );
GLsizei len;
glGetShaderInfoLog( id, maxLen, &len, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
Further, I recommend to use Raw string literals:
std::string fragmentShader = R"(
#version 330 core
layout(location=0) out vec4 color;
void main()
{
color=vec4(1.0, 0.0, 0.0, 1.0);
}
)";
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.
I'm attempting to use VAO's+VBO's+IBO's with shaders, but no object gets drawn. I am not sure what I am missing. I am pretty new to C++, and GLSL, so I am not sure if I am screwing something up with the C++ in general, or if I am failing to handle the OpenGL context correctly?
The main function (code for handling window creation is missing. If you think you may need to review it as well, just let me know.):
int main(int argc, char *argv[])
{
//INIT SDL
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(400, 300, SDL_WINDOW_OPENGL, &displayWindow, &displayRenderer);
SDL_GetRendererInfo(displayRenderer, &displayRendererInfo);
/*TODO: Check that we have OpenGL */
if ((displayRendererInfo.flags & SDL_RENDERER_ACCELERATED) == 0 || (displayRendererInfo.flags & SDL_RENDERER_TARGETTEXTURE) == 0) {}
SDL_GL_CreateContext(displayWindow);
//SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glewInit();
int error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during glewInit call: " << error << "\n"; };
//glEnable(GL_DEBUG_OUTPUT);
Display_InitGL();
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during Display init: " << error << "\n"; };
Display_SetViewport(400, 300);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during Display Set Viewport Issue: " << error << "\n"; };
// SET UP TEST OBJ
MainChar *player = new MainChar();
player->MainChar_VBO_Func();
GLushort size = player->MainChar_VBO_IndexBuffer_Func();
float count = 0.0;
// END SET UP OF TEST OBJ
GLint *length = new GLint;
const char* vertShdr = readFile("C:\\Users\\JRFerrell\\Documents\\Visual Studio 2013\\Projects\\GLEW Practice\\vertShader.vs", *length);
std::cout << vertShdr;
GLuint vertShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShaderId, 1, &vertShdr, length);
std::cout << "\n\nLength: " << *length;
glCompileShader(vertShaderId);
GLint *length2 = new GLint;
const char* fragShdr = readFile("C:\\Users\\JRFerrell\\Documents\\Visual Studio 2013\\Projects\\GLEW Practice\\fragShader.fs", *length2);
GLint fragShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShaderId, 1, &fragShdr, length2);
glCompileShader(fragShaderId);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertShaderId);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during glAttachShader: " << error << "\n"; };
glAttachShader(shaderProgram, fragShaderId);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during glAttachShader: " << error << "\n"; };
glBindAttribLocation(shaderProgram, 0, "in_Position");
glBindAttribLocation(shaderProgram, 1, "in_Normal");
glLinkProgram(shaderProgram);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error during glLinkProgram: " << error << "\n"; };
// END SHADER PROGRAM DEFINITION
//Check info log for errors:
int Len = 0;
char *Buffer = nullptr;
glGetShaderiv(vertShaderId, GL_INFO_LOG_LENGTH, &Len);
Buffer = new char[Len];
glGetShaderInfoLog(vertShaderId, Len, &Len, Buffer);
std::cout << "Vertex Log:" << std::endl << Buffer << std::endl;
delete[] Buffer;
glGetShaderiv(fragShaderId, GL_INFO_LOG_LENGTH, &Len);
Buffer = new char[Len];
glGetShaderInfoLog(fragShaderId, Len, &Len, Buffer);
std::cout << "Fragment Log:" << std::endl << Buffer << std::endl;
delete[] Buffer;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &Len);
Buffer = new char[Len];
glGetProgramInfoLog(shaderProgram, Len, &Len, Buffer);
std::cout << "Shader Log:" << std::endl << Buffer << std::endl;
delete[] Buffer;
// Create VAO. Don't forget to enable all necessary states because the VAO starts with default state, cleaning all states prev called to do so.
GLuint VaoId;
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
// Bind buffers & set-up VAO vertex pointers
glBindBuffer(GL_ARRAY_BUFFER, player->vboID);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error glBindBuffer-vboID: " << error << "\n"; }
glEnableClientState(GL_VERTEX_ARRAY);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * GL_FLOAT, (const GLvoid *)0);
glEnableVertexAttribArray(0);
// Set-up VAO normal pointers
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error glBindBuffer-vbo init: " << error << "\n"; }
glEnableClientState(GL_NORMAL_ARRAY);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * GL_FLOAT, (void*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, player->vboIndexID);
GLint maxLength, nAttribs;
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs);
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &maxLength);
//std::cout << "\nmax length: " << maxLength << "\nnAttribs: " << nAttribs;
glBindVertexArray(0);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error glBindVertexArray: " << error << "\n"; };
// End VAO init
while (1){
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error glClearColor: " << error << "\n"; };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
error = glGetError();
if (error != GL_NO_ERROR){ std::cout << "Error in glClear: " << error << "\n"; };
glLoadIdentity();
glUseProgram(shaderProgram);
glBindVertexArray(VaoId);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT, 0);
glUseProgram(0);
glBindVertexArray(0);
SDL_GL_SwapWindow(displayWindow);
count -= .1;
}
SDL_Delay(5000);
SDL_Quit();
return 0;
}
::The shader code::
Vertex shader:
#version 400
in vec3 in_Position;
in vec3 in_Normal;
void main()
{
gl_Position = vec4(in_Position, 1.0);
}
Fragment shader:
#version 400
out vec4 FragColor;
void main()
{
FragColor = vec4(0.0f, 0.5f, 1.0f, 1.0f);
}
I did look at similar questions on here already, and they did help me fix a few possible issues, but so far, they obviously haven't proven useful in helping me get my code up and running. I also asked some other people in real time chat on gamedev.net, but they couldn't seem to see where I went wrong either. I fixed a possible issue with declaring glDoubles rather than floats, but that was actually working without the vao and shaders, so that is not (and unlikely ever was) the issue, in whole or part.
I don't know if any of the following will solve your problem, but I do see some issues in your code:
glEnableClientState(GL_VERTEX_ARRAY);
You are mixing here old and deprecated builtin vertex atttributes with the generic vertex attributes. You don't need any of these glEnableClientState calls - your shader doesn't use the builtin attributes. The same goes for the glLoadIdentity which is also totally unneeded and would be invalid in a core profile context.
The second thing I see is that you do not specify your attribute indices, so the GL is free to map them. You also don't query them, but just assume them to be 0 for in_Position and 1 for in_Normal - which is by no means guaranteed to be the case. Use the layout(location=) qualifiers when declaring your input attributes in your vertex shader to actually define the mapping, or use glBindAttribLocation.
quickly looking over your code I am struggling to find where you are sending the BufferData to the GPU.
Generate and Bind new buffer
Initialise Buffers to take data.
Send data using glBufferSubData...
Repeat steps 1 through 3 for Element Arrays.
Generate and Bind Vertex Array Object.
Setup VertexAttribArray Pointers and bind them to your shader.
Bind Element Buffer once again.
Unbind Vertex Array using glBindVertexArray(0)
This is how I setup my buffers using OpenTK, the code should be fairly understandable and useful in any case:
// Generate Vertex Buffer Object and bind it so it is current.
GL.GenBuffers(1, out bufferHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferHandle);
// Initialise storage space for the Vertex Buffer.
GL.BufferData(BufferTarget.ArrayBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StaticDraw);
// Send Position data.
GL.BufferSubData<Vector3>(
BufferTarget.ArrayBuffer, noOffset, new IntPtr(sizeOfPositionData), bufferObject.PositionData);
// Send Normals data, offset by size of Position data.
GL.BufferSubData<Vector3>(
BufferTarget.ArrayBuffer, new IntPtr(sizeOfPositionData), new IntPtr(sizeOfNormalsData), bufferObject.NormalsData);
// Generate Element Buffer Object and bind it so it is current.
GL.GenBuffers(1, out bufferHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferHandle);
GL.BufferData(
BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * bufferObject.IndicesData.Length), bufferObject.IndicesData, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferObject.IboID);
// Generate Vertex Array Object and bind it so it is current.
GL.GenVertexArrays(1, out bufferHandle);
GL.BindVertexArray(bufferHandle);
bufferHandle = GL.GetAttribLocation(program, "in_position");
GL.EnableVertexAttribArray(bufferHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
GL.BindAttribLocation(program, bufferHandle, "in_position");
bufferHandle = GL.GetAttribLocation(program, "in_normal");
GL.EnableVertexAttribArray(bufferHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, sizeOfPositionData);
GL.BindAttribLocation(program, bufferHandle, "in_normal");
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferObject.IboID);
// IMPORTANT: vertex array needs unbinding here to avoid rendering incorrectly
GL.BindVertexArray(0);
Well, after sitting down and reading the docs for version 4.0, I learned that I had screwed up on my attrib pointers by passing incorrect stride and pointers to the start of the buffer data. My thought was that the stride was the size of the element type multiplied by the number of attribute elements, so you'd get the next attribute you were looking for. Obviously that is not what you are supposed to do. I changed that to zero since my attribs are back to back:
"glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * GL_FLOAT, (void*)(3 * sizeof(GL_FLOAT)));"
-->
"glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3 * sizeof(GL_FLOAT)));"
Then the pointer I tried handling almost the same exact way. Should have been a null pointer to the first buffer attrib location:
"glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3 * sizeof(GL_FLOAT)));"
-->
"glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);"
Once I actually sat down and read the docs closely, I understood what actually belonged there. Now the shaders are working and I can work on the cool stuff... :P Thanks for the efforts to answer my question anyways everyone. :)