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);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
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.
Closed 1 year ago.
Improve this question
I'm trying to get OpenGL to render a basic triangle with shaders on my newer Macbook Pro with the M1 chip. I'm stuck using Qt Creator as well.
I was able to set it up and get a basic Fixed-Pipeline scene rendering, but when I changed the version to use modern OpenGL I get that the version is 4.1, even though I set it to 3.2.
Here's how I set the version:
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setMajorVersion(3);
format.setMinorVersion(2);
QSurfaceFormat::setDefaultFormat(format);
this->setFormat(format); // must be called before the widget or its parent window gets shown
When I print out the shader sources I can see that I'm getting exactly what I put into my vertex shader and fragment shader files, so I know that I'm loading in the files correctly. Here's how I'm using them inside of my Shader class:
programID = glCreateProgram(); // Creates the program ID
vs = glCreateShader(GL_VERTEX_SHADER); // Creates the vertex shader
fs = glCreateShader(GL_FRAGMENT_SHADER); // Creates the fragment shader
// Shader reading code removed...
const char* vSrc = vSource.c_str();
int size = vSource.size();
glShaderSource(vs, 1, &vSrc, &size);
glCompileShader(vs);
int result;
glGetShaderiv(vs, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int length;
glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &length);
char* msg = new char[length];
glGetShaderInfoLog(vs, length, &length, msg);
std::cout << "Vertex Shader Message:\n" << msg << std::endl;
exit(1);
}
const char* fSrc = fSource.c_str();
int size2 = fSource.size();
glShaderSource(fs, 1, &fSrc, &size2);
glCompileShader(fs);
int result2;
glGetShaderiv(fs, GL_COMPILE_STATUS, &result2);
if (result2 == GL_FALSE)
{
int length;
glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &length);
char* msg = new char[length];
glGetShaderInfoLog(fs, length, &length, msg);
std::cout << "Fragment Shader Message:\n" << msg << std::endl;
exit(1);
}
glAttachShader(programID, vs);
glAttachShader(programID, fs);
glLinkProgram(programID);
glValidateProgram(programID);
And then in my initOpenGL function I have:
float positions[6] =
{
-0.5, -0.5,
0.0, 0.5,
0.5, -0.5
};
glGenBuffers(1, ¤tBuffer); // Generates the buffer
glBindBuffer(GL_ARRAY_BUFFER, currentBuffer); // Binds it before we use it
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW); // Sends the data to OpenGL
glEnableVertexAttribArray(0); // Enables the buffer layout
glBindBuffer(GL_ARRAY_BUFFER, currentBuffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); // Tells OpenGL how we stored the data
s = new Shader("main.vsh", "main.fsh");
glUseProgram(s->getShaderID());
Then, I render the data with the following call in my render function:
glDrawArrays(GL_TRIANGLES, 0, 3);
Here is the vertex shader code:
#version 410 core
layout (location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
Here is the fragment shader code:
#version 410 core
layout (location = 0) out vec4 color;
void main(void)
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
This is not a problem with the shaders. However in a core profile OpenGL Context you have to create Vertex Array Object, since the default VAO (0) is not valid. This is not optional:
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0); // Enables the buffer layout
glBindBuffer(GL_ARRAY_BUFFER, currentBuffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0)
You have to bind the VAO before the vertex specification. The vertex specification is stored in the VAO.
The vertex specification stored in the currently bound VAO is used when drawing a mesh. Hence, you need to make sure the VAO is bound before the drawing command as well:
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
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.
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;
}
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.
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.