Garbled Triangles from VBO/Shader/MVP Matrix using OpenGL 3.3 - c++

Drawing with a regular VBO on older GLSL versions is not a problem but for whatever reason I get this result when using GLSL 3.3.
It should be drawing a 2x2 plane on each axis.
(Lighter colors are closer to the far plane, darker are closer to the near plane)
One of the major changes with 3.3 was that you have to provide uniforms with your Model View Projection matrixes as opposed to using the old provided ones.
I don't know what I'm doing wrong but I'm almost certain it's something to do with the Model View Projection data. Here is the relevant code.
Main draw method
float r = 0.0f;
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glClear(GL_DEPTH_BUFFER_BIT); // And the depth buffer
r += 0.001f;
glUseProgram(program);
glEnable(GL_DEPTH_TEST);
GLuint uniformModel = glGetUniformLocation(program, "model");
GLuint uniformView = glGetUniformLocation(program, "view");
GLuint uniformProjection = glGetUniformLocation(program, "projection");
glm::mat4 projection = glm::perspective(70.0f, 1.0f, 0.0f, 16.0f);
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
glm::vec3 eye = glm::vec3(sin(r*0.33)*5.0f,5,cos(r*0.33)*5.0f);
glm::vec3 center = glm::vec3(0.0f,0.0f,0.0f);
glm::vec3 up = glm::vec3(0.0f,0.0f,1.0f);
glm::mat4 view = glm::lookAt(eye, center, up);
glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(view));
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f,0.0f,0.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_INT, indices);
glDisableVertexAttribArray(0);
glDisable(GL_DEPTH_TEST);
glUseProgram(0);
glFlush(); // Render now
}
Vertex/Indices Array & Shader
string vert
= "#version 330 core\n"
"layout(location = 0) in vec3 vertex;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main(){\n"
" gl_Position = projection * view * model * vec4(vertex,1.0f);\n"
"}";
string frag
= "#version 330 core\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" float lin = 1.0 / gl_FragCoord.w;\n"
" float depth = (lin - 0.1) / (16.0 - 0.1);\n"
" color = vec3(depth,depth,1.0f);\n"
"}";
float* data = new float[36] {
-1.0f,-1.0f,0.0f,
1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
0.0f,-1.0f,-1.0f,
0.0f,1.0f,-1.0f,
0.0f,1.0f,1.0f,
0.0f,-1.0f,1.0f,
-1.0f,0.0f,-1.0f,
1.0f,0.0f,-1.0f,
1.0f,0.0f,1.0f,
-1.0f,0.0f,1.0f
};
GLuint* indices = new GLuint[18] {
0,1,2,
0,3,2,
4,5,6,
4,7,6,
8,9,10,
8,11,10
};
Init
const int winSize = 1024;
void glInit(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitContextVersion(3,3);
//glutInitContextFlags(GLUT_CORE_PROFILE | GLUT_DEBUG);
glutInitWindowSize(winSize, winSize);
glutInitWindowPosition(25, 25);
glutCreateWindow("Loading...");
glewExperimental = GL_TRUE;
glewInit();
glViewport (0, 0, winSize, winSize);
camera.setPosition(0.0f,0.0f,4.0f);
glGenVertexArrays(1, &vba);
glBindVertexArray(vba);
program = compileShader(vert, frag);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 3*4*3*4, data, GL_STATIC_DRAW);
glEnable(GL_DEPTH_TEST);
while(!bExit) {
string pre;
pre.assign("Test Program - ");
pre.append(std::to_string(fps));
glutSetWindowTitle(pre.c_str());
frames++;
display();
}
}

Turns out I'm an idiot and it was just a typo kind of error.
I define GLuint vbo in the init method AND on the scope of the program as well but the actual value of the vbo is only put into local variable. display() didn't have visibility of the vbo at all.
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
It's always the little things that cause ridiculous bugs. <_>

Related

Rotated GLSL texture is pixelated

I've made a program that displays some textures depending on the given input and can rotate, resize and move the textures depending on the given input. The program works perfectly fine but when I rotate the textures the edges appear to be pixelated, like this:
Is there a way for me to smoothen out these edges?
Here are my shaders and texture classes:
texture.vs:
#version 300 es
precision mediump float;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(aPos, 1.0f);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
texture.fs
#version 300 es
precision mediump float;
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
Here is my texture.cpp:
Texture::Texture(int x, int y, int w, int h, int gw, int gh)
{
pos.TL_x = _VERTICIZE_X(x, gw);
pos.TL_y = -_VERTICIZE_Y(y, gh);
pos.TR_x = _VERTICIZE_X(x + w, gw);
pos.TR_y = -_VERTICIZE_Y(y, gh);
pos.BL_x = _VERTICIZE_X(x, gw);
pos.BL_y = -_VERTICIZE_Y(y + h, gh);
pos.BR_x = _VERTICIZE_X(x + w, gw);
pos.BR_y = -_VERTICIZE_Y(y + h, gh);
}
void set_max_z(int z)
{
max_z = z;
}
int Texture::init(float ang_rad, float z)
{
shader = Shader("./src/opengl/shaders/image.vs", "./src/opengl/shaders/image.fs");
this->angle = ang_rad;
// build and compile our shader zprogram
// ------------------------------------
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[32] = {
// positions // colors // texture coords
pos.TR_x, pos.TR_y, _VERTICIZE_Z(z, max_z), 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // top right
pos.BR_x, pos.BR_y, _VERTICIZE_Z(z, max_z), 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, // bottom right
pos.BL_x, pos.BL_y, _VERTICIZE_Z(z, max_z), 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // bottom left
pos.TL_x, pos.TL_y, _VERTICIZE_Z(z, max_z), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
glEnable(GL_DEPTH_TEST);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// load and create a texture
// -------------------------
// texture 1
// ----------
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
shader.use(); // don't forget to activate/use the shader before setting uniforms!
// either set it manually like so:
glUniform1i(glGetUniformLocation(shader.ID, "texture"), 0);
return 0;
}
void Texture::render(int w, int h, uint8_t *buffer)
{
// If having trouble doing multiple textures, add "+ index to Active Texture."
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glGenerateMipmap(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glm::mat4 transform = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
transform = glm::translate(transform, glm::vec3(0.0f, 0.0f, 0.0f));
transform = glm::rotate(transform, glm::radians(this->angle), glm::vec3(0.0f, 0.0f, 1.0f));
// get matrix's uniform location and set matrix
shader.use();
unsigned int transformLoc = glGetUniformLocation(shader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
Texture::~Texture()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
void Texture::framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
(_VERTICIZE just calculates points)
I'm using ubuntu, GLAD, GLFW.
This appears to be a classic example of Aliasing. We can fix this by enabling MSAA.
GLFW has an inbuilt way of doing that. Put this before you create the window:
glfwWindowHint(GLFW_SAMPLES, 4); /* if effect is not strong enough, change to 8 */
Edit -
You have to call glfwWindowHint(GLFW_SAMPLES, 4) in between glfwInit and glfwCreateWindow.
Also, in case OpenGL doesn't enable multisampling by default, do
glEnable(GL_MULTISAMPLE);

Drawing multiple objects with shaders (GLEW)

I want to draw different figures using triangle fans but I am not sure how to make the program draw the second figure. Do I need a second vertexShaderSource and a second fragmentShaderSource each time I want to change the color or draw a new figure?
Here is the code:
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n""void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);\n" // To set the color.
"}\n\0";
// Set of vertices for the different figures that make up the drawing.
float vertices[] = {
-0.8f, 0.6f, 0.0f, // Center.
-0.8f, 0.4f, 0.0f,
-0.83f, 0.44f, 0.0f,
-0.87f, 0.51f, 0.0f,
-0.9f, 0.57f, 0.0f,
-0.93f, 0.63f, 0.0f,
-0.95f, 0.69f, 0.0f,
-0.97f, 0.75f, 0.0f,
-0.98f, 0.8f, 0.0f,
-0.91f, 0.8f, 0.0f,
-0.85f, 0.79f, 0.0f,
-0.8f, 0.77f, 0.0f,
};
unsigned int VBO, VAO;
GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;
void display(void){
// Background color.
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glBindVertexArray(0);
glFlush();
}
// Main.
int main(int argc, char** argv){
glutInit(&argc, argv);
// Color mode.
glutInitDisplayMode(GLUT_RGBA);
// Window size.
glutInitWindowSize(500, 500);
// Title.
glutCreateWindow("Tarea 3: Figura con curvas");
GLenum err = glewInit();
if(err!=GLEW_OK) {
printf("glewInit failed: %s",glewGetErrorString(err));
exit(1);
}
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glutDisplayFunc(display);
glutMainLoop();
}
No is not necessary (or recommended) to use different shaders for the meshes. If you want to draw multiple objects, then you can put the vertex attributes of the meshes to separate Vertex Buffer Objects:
GLuint VBOs[2];
glGenBuffers(2, VBOs);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices_1, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices_2, GL_STATIC_DRAW);
Specify a Vertex Array Object for each mesh:
GLuint VAOs[2];
glGenVertexArrays(2, VAOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
Bind the VAO, before the draw call:
glBindVertexArray(VAOs[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
glBindVertexArray(VAOs[1]);
glDrawArrays(...);
Of course it is also possible to put all the vertex attributes of the different meshes consecutively in the data store of one VBO. If the vertex specification is identically, then it is event possible to use one single VAO.
Different locations of different meshes can be achieved by vertex transformation in the vertex shader. Use a Uniform of type mat4, to transform the vertices of a mesh:
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 u_model;
void main()
{
gl_Position = u_model * vec4(aPos.xyz, 1.0);
}
See further LearnOpenGL - Transformations.
If the 2 figures are identical, but have just a different location, then you can draw the same mesh twice, but you have to change the model transformation u_model.
You are looking for Uniform buffer objects.
If you have only a single value for a whole draw call, then your shader should be parametrized. The obvious thing you want to parametrize first is the color in the fragment shader, followed by adding a projection matrix to the vertex shader.
From that point onwards it's just alternating between setting new values to uniforms and draw-calls as long as it is the same 3D model.
For different models refer to #rabbid76's answer.

Why stencil test does not discard fragments?

I want to run stencil test to outline cubes. It is from learnopengl https://learnopengl.com/Advanced-OpenGL/Stencil-testing.
A cubes that do outlining should have discarded fragments that are on a textured cubes. It does not happen, the outlining cubes cover the whole area.
static const char* cubeVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec2 a_uv;
out vec2 v_uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
v_uv = a_uv;
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* cubeFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
in vec2 v_uv;
uniform sampler2D u_texture1;
void main()
{
f_color = texture(u_texture1, v_uv);
}
)";
static const char* singleColorVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* singleColorFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
void main()
{
f_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
)";
void Cube::InitAPI()
{
shader = Shader::Create();
ShaderProgram program[2] = {
shader->ShaderFromSource(cubeVtx, ShaderType::Vertex),
shader->ShaderFromSource(cubeFrag, ShaderType::Fragment)
};
shader->End(program, 2);
singleColorShader = Shader::Create();
ShaderProgram singleColorProgram[2] = {
singleColorShader->ShaderFromSource(singleColorVtx, ShaderType::Vertex),
singleColorShader->ShaderFromSource(singleColorFrag, ShaderType::Fragment)
};
singleColorShader->End(singleColorProgram, 2);
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glNamedBufferData(vbo, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glCreateVertexArrays(1, &planeVao);
glBindVertexArray(planeVao);
glCreateBuffers(1, &planeVbo);
glBindBuffer(GL_ARRAY_BUFFER, planeVbo);
glNamedBufferData(planeVbo, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
texture = Texture::LoadPNG("Media/container2");
planeTexture = Texture::LoadPNG("Media/matrix");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
shader->UseProgram();
shader->Uniform1i("u_texture1", 0);
}
void Cube::Render()
{
singleColorShader->UseProgram();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)1280.0f / (float)720.0f, 0.1f, 100.0f);
singleColorShader->UniformMatrix4fv("view", view);
singleColorShader->UniformMatrix4fv("projection", projection);
shader->UseProgram();
shader->UniformMatrix4fv("view", view);
shader->UniformMatrix4fv("projection", projection);
glStencilMask(0x00);
glBindVertexArray(planeVao);
planeTexture->Active();
planeTexture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glBindVertexArray(vao);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader->UniformMatrix4fv("model", model);
texture->Active();
texture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
singleColorShader->UseProgram();
float scale = 1.1;
glBindVertexArray(vao);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
}
Test::Test()
{
//tried many patterns and stencil values
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
window = SDL_CreateWindow("window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
glewExperimental = true;
glewInit();
cube.InitAPI();
}
void Test::MainLoop()
{
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
}
I still quite do not get the depth test thing and when I started thinking that I am getting stencil test, it all messed up, because it does not work.
Yes, I do clear color, depth and stencil buffer, somewhere else, but before Render() method.
What I got:
What I expect is a red outline, not the whole cube
Could you please explain like I were an idiot why it does not discard fragments that are 1
Call SDL_Init, before calling any other SDL-function
SDL_Init(SDL_INIT_EVERYTHING);
See the documentation of SDL_Init():
Use this function to initialize the SDL library. This must be called before using most other SDL functions.
To make the stencil buffer work, the SDL_GL_STENCIL_SIZE attribute has to be set. By default this attribute is 0. In general a stencil buffer has 8 bits. e.g.:
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute has to be called before SDL_CreateWindow else it won't have any effect.
See the documentation of SDL_GL_SetAttribute:
Use this function to set an OpenGL window attribute before window creation.
The original code calls SDL_Init after SDL_GL_SetAttribute()
The code above, does not even call SDL_Init. Initializing SDL fixes everything.

glViewport inside loop cause smaller view port

I've a simple OpenGL program running on macOS:
glUseProgram(program);
glViewport(0, 0, mWidth, mHeight);
glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
// Rendering Loop
while (glfwWindowShouldClose(mWindow) == false) {
if (glfwGetKey(mWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(mWindow, true);
}
// why can't view port here?
glViewport(0, 0, mWidth, mHeight);
// Background Fill Color
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Flip Buffers and Draw
glfwSwapBuffers(mWindow);
glfwPollEvents();
}
If I comment out the glViewport call inside the loop, it works well, the triangle is rendered in the center of the window, but if I uncomment it, the triangle shows in the left bottom corner of the window.
Below is my shader and vertex data code:
const int mWidth = 1280;
const int mHeight = 800;
auto mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGL", nullptr, nullptr);
const GLchar* vertex_shader_src =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}";
const GLchar* fragment_shader_src =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}";
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Could somebody help me?
As #httpdigest commented, it is because macOS has 2x larger frame buffer size, if I query it with glfwGetFramebufferSize and use it as view port size, it works well!

Model, view and projection matrix do not want to work well for opengl glsl

I am trying to make my first cube using open gl. Unfortunately I stucked in easy rotation. This is how it should look:
Instead I am getting those weird, do not even know how to called it : https://youtu.be/0A5Hi-8bygE
Vertex shader
#version 330 core
layout (location = 0) in vec2 a_position;
layout (location = 1) in vec2 a_uv;
layout (location = 2) in vec4 a_color;
out vec2 v_fragmentPosition;
out vec2 v_fragmentUV;
out vec4 v_fragmentColor;
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
v_fragmentPosition = a_position;
v_fragmentUV = vec2(a_uv.x, 1 - a_uv.y);
v_fragmentColor = a_color;
}
Fragment
#version 330 core
out vec4 outColor;
in vec2 v_fragmentPosition;
in vec2 v_fragmentUV;
in vec4 v_fragmentColor;
void main()
{
outColor = v_fragmentColor;
}
Main
#include <glad.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <iostream>
#include "Mesh.h"
#include "Shader.h"
int main(int argc,char*args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow("fdas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(window);
gladLoadGLLoader(SDL_GL_GetProcAddress);
glEnable(GL_DEPTH_TEST);
Shader shader;
std::string vertex = shader.LoadFromFile("vertex.shader");
std::string fragment = shader.LoadFromFile("fragment.shader");
shader.CreateShaderProgram(vertex.c_str(), fragment.c_str());
shader.useProgram();
Mesh mesh;
mesh.CreateVertexArray();
bool quit = false;
SDL_Event event;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
exit(0);
}
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model;
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), 1280 / 720.0f, 0.1f, 100.0f);
GLint u_model = shader.GetUniformLocation("u_model");
GLint u_view = shader.GetUniformLocation("u_view");
GLint u_projection = shader.GetUniformLocation("u_projection");
glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(u_view, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));
Rect destRect = { -0.5f, -0.5f, 1.0f, 1.0f };
Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };
ColorRGBA color = { 255, 255, 128, 255 };
mesh.CreateQuad(destRect, uvRect, color);
mesh.Draw(0);
SDL_GL_SwapWindow(window);
}
return 0;
}
Mesh
void Mesh::CreateVertexArray()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glBindVertexArray(0);
}
void Mesh::CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color)
{
vertex[0].color = color; // topleft
vertex[0].setPosition(destRect.x, destRect.y + destRect.h);
vertex[0].setUV(uvRect.x, uvRect.y + uvRect.h);
vertex[1].color = color;
vertex[1].setPosition(destRect.x, destRect.y); // bottom left
vertex[1].setUV(uvRect.x, uvRect.y);
vertex[2].color = color;
vertex[2].setPosition(destRect.x + destRect.w, destRect.y); // bottom right
vertex[2].setUV(uvRect.x + uvRect.w, uvRect.y);
vertex[3].color = color;
vertex[3].setPosition(destRect.x + destRect.w, destRect.y + destRect.h); // top right
vertex[3].setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);
GLuint indices[6] = {
0, 1, 2,
2, 3, 0
};
glBindVertexArray(vao);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(vertex), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(vertex), vertex);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), indices);
glBindVertexArray(0);
}
void Mesh::Draw(GLuint texture)
{
glBindVertexArray(vao);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_FRONT);
//glFrontFace(GL_CW);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
Vertex
struct Rect {
float x, y;
float w, h;
};
struct Position {
float x, y;
};
struct UV {
float u, v;
};
struct ColorRGBA {
GLubyte r, g, b, a;
};
class Vertex
{
public:
Vertex();
~Vertex();
void setPosition(float x, float y);
void setcolor(ColorRGBA color);
void setUV(float u, float v);
UV uv;
ColorRGBA color;
Position position;
};
I will not show shader class, because there is all good with it.
I know it, because I did an experiment.
I created a new uniform in fragment class called u_expColor and set outColor = u_expColor and a quad's color changed.
Also I created uniform vec4 u_expPos in vertex shader and said gl_Position = e_expPos and it created quad with no problems.
Only if I want to create/multiply position by mvp in vertex shader there is a problem like on the you tube video.
How to fix it?
I have fixed it thanks http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#putting-it-all-together. I saw he had
glm::mat4 model = glm::mat4(1.0f)
and it was all I had to do.