Related
I'm trying to use a compute shader to do three-dimensional physical simulations but having trouble storing anything into my 3D texture. My shaders compile successfully but when reading back any value from the 3D texture I get a zero vector. I haven't used compute shaders before either so I'm not sure if I'm even distributing the work load properly in order to achieve what I want.
I've isolated the problem in a small example here. Basically the compute.glsl shader has a uniform image3D and uses imageStore to write a vec4(1,1,0,1) into gl_WorkGroupID. In C++ I create a 100x100x100 3D texture and bind it to the shader's uniform, then I call glDispatchCompute(100,100,100) - to my knowledge, this will create 1,000,000 jobs/shader invocations, one for each coordinate in the texture. In my view.glsl fragment shader I read the value of a random coordinate (in this case (3,5,7)) and output that. I use this shade a cube object.
Everything I've tried results in a black cube being output:
Here's my code (I've been following along with learnopengl.com so it's mostly the same boiler plate stuff except I extended the shader class to handle compute shaders):
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <learnopengl/shader_m.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
struct vaoinfo
{
unsigned int VBO, VAO, EBO;
vaoinfo() : VAO(0), VBO(0), EBO(0)
{}
};
void create_vao(vaoinfo& info)
{
glGenVertexArrays(1, &info.VAO);
glGenBuffers(1, &info.VBO);
glGenBuffers(1, &info.EBO);
}
void init_vao(vaoinfo& info, float* vertices, int num_vertices, int* indices, int num_indices)
{
glGenVertexArrays(1, &info.VAO);
glGenBuffers(1, &info.VBO);
glGenBuffers(1, &info.EBO);
glBindVertexArray(info.VAO);
glBindBuffer(GL_ARRAY_BUFFER, info.VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_vertices, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, info.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * num_indices, indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
vaoinfo cube;
create_vao(cube);
glm::vec3 c(0.5, 0.5, 0.5);
float verts[24] =
{
c.x, -c.y, c.z,
c.x, c.y, c.z,
-c.x, c.y, c.z,
-c.x, -c.y, c.z,
c.x, -c.y, -c.z,
c.x, c.y, -c.z,
-c.x, c.y, -c.z,
-c.x, -c.y, -c.z,
};
int indices[36] =
{
7, 4, 5,
5, 6, 7,
3, 0, 1,
1, 2, 3,
2, 6, 7,
7, 3, 2,
1, 5, 4,
4, 0, 1,
7, 4, 0,
0, 3, 7,
6, 5, 1,
1, 2, 6
};
init_vao(cube, verts, 24, indices, 36);
// Create a 3D texture
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_3D, texId);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8_SNORM, 100, 100, 100, 0, GL_RGBA, GL_FLOAT, nullptr);
// Create shaders
Shader computeShader("compute.glsl");
Shader viewShader("coords.glsl", "view.glsl");
while (!glfwWindowShouldClose(window))
{
processInput(window);
computeShader.use();
computeShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId);
glDispatchCompute(100, 100, 100);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
viewShader.use();
viewShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId);
glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
unsigned int modelLoc = glGetUniformLocation(viewShader.ID, "model");
unsigned int viewLoc = glGetUniformLocation(viewShader.ID, "view");
unsigned int projLoc = glGetUniformLocation(viewShader.ID, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// render cube
glBindVertexArray(cube.VAO);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
compute.glsl:
#version 430
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(rgba8_snorm, binding=0) uniform image3D img;
uniform vec3 position;
void main()
{
ivec3 voxel_coord = ivec3(gl_WorkGroupID);
imageStore(img, voxel_coord, vec4(1, 1, 0, 1));
}
coords.glsl (vertex shader):
#version 430 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
view.glsl (fragment shader):
#version 430 core
out vec4 FragColor;
layout(rgba8_snorm, binding=0) uniform image3D img;
void main()
{
FragColor = imageLoad(img, ivec3(3,5,7));
}
It turned out that I was missing a call to glBindImageTexture - I thought that in order to bind my texture to the shader's image variable I needed to set the uniform and call glActiveTexture+glBindTexture but it seems only glBindImageTexture is needed.
I replaced:
computeShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId)
With:
glBindImageTexture(0, texId, 0, true, 0, GL_WRITE_ONLY, GL_RGBA16);
I'm using GLFW, OpenGL 4.6 with VSCode, and MinGW64 g++. I'm trying to render a transparent texture using glEnable(GL_BLEND); and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);. Whilst the texture does render on my window, it seems like the glClearColor() affects the blend significantly. I'm still very new to graphics, so I'm not sure how I can render the texture properly regardless of what the clear color is set to. Also, do I need to enable Depth for 2D games? (shader.cpp and texture.cpp is taken from The Cherno's OpenGL tutorial series)
Without blend
With blend
With blend and black clear color (Desired blend)
main.cpp:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "GeometryUtil.h"
#include "Shader.h"
#include "Texture.h"
#include "Object.h"
#include <iostream>
#include <vector>
using namespace std;
int main() {
if (!glfwInit()) { // Initialise GLFW
cerr << "Failed to initialize GLFW" << endl;
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window {glfwCreateWindow(1280, 720, "2D GAME", NULL, NULL)};
if (window == NULL) {
cerr << "Failed to open GLFW window." << endl;
glfwTerminate();
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK) {
cerr << "Failed to initialize GLEW" << endl;
glfwTerminate();
return -1;
}
cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
Object object {608, 392};
vector<float> vectorData;
createQuad(object.getX(), object.getY(), vectorData);
static const GLfloat texCoords[8] {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
GLuint VBOs[2];
glGenBuffers(2, VBOs);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, vectorData.size() * sizeof(vectorData), &vectorData.front(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) 0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
static const GLuint texIndex[6] {
0, 1, 2,
1, 2, 3
};
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(texIndex), texIndex, GL_STATIC_DRAW);
glm::mat4 Projection {glm::ortho(0.0f, 1280.0f, 0.0f, 720.0f, 0.0f, 1.0f)};
glm::mat4 View {glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0))};
glm::vec3 translationA {glm::vec3(0, 0, 0)};
glm::mat4 Model = glm::translate(glm::mat4(1.0f), translationA); // Model Matrix (Using Identity Matrix - Origin)
glm::mat4 mvp = Projection * View * Model;
Shader shader {"shader/vertexShader.vert", "shader/fragmentShader.frag"};
shader.bind();
shader.setUniformMat4f("MVP", mvp);
int sampler[] {0, 1};
shader.setUniform1iv("v_Textures", sampler, 2);
Texture texture {"resources/sprites/test.png"};
texture.bind();
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
texture.cpp:
#define STB_IMAGE_IMPLEMENTATION
#include <GL/glew.h>
#include "Texture.h"
#include "stb_image.h"
#include <iostream>
Texture::Texture(const std::string &path)
: rendererID{0}, filePath{path}, localBuffer{nullptr}, width{0}, height{0}, bPP{0} {
// stbi_set_flip_vertically_on_load(1);
localBuffer = stbi_load(path.c_str(), &width, &height, &bPP, 4);
if (localBuffer == nullptr)
std::cout << "Unable to load texture file: " << path << std::endl;
glGenTextures(1, &rendererID);
glBindTexture(GL_TEXTURE_2D, rendererID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer);
unbind();
if (localBuffer)
stbi_image_free(localBuffer);
}
Texture::~Texture() {
glDeleteTextures(1, &rendererID);
}
void Texture::bind(GLuint slot) const {;
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, rendererID);
}
void Texture::unbind() const {
glBindTexture(GL_TEXTURE_2D, 0);
}
vertex shader:
#version 460 core
layout(location = 0) in vec3 vertexCoords;
layout(location = 1) in vec2 textureCoords;
layout(location = 2) in float textureIndex;
out vec2 v_TexCoords;
out float v_TexIndex;
uniform mat4 MVP;
void main() {
gl_Position = MVP * vec4(vertexCoords, 1.0);
v_TexCoords = textureCoords;
v_TexIndex = textureIndex;
}
fragment shader:
#version 460 core
in vec2 v_TexCoords;
in float v_TexIndex;
uniform sampler2D v_Textures[2];
void main() {
gl_FragColor = texture2D(v_Textures[int(v_TexIndex)], v_TexCoords);
}
Everthing is correct codewise on the first look, and yes, the Background will affect the Blending in the case of GL_SRC_ALPHA as first pararmeter.
The issue is the second parameter which should be GL_ONE_MINUS_SRC_ALPHA instead of GL_ONE_MINUS_SRC1_ALPHA. In your case the blend is not normalized and so the values of too much green and a full red add up to that yellowish.
source: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFuncSeparate.xhtml
This is an error that appears when trying to load the texture:
This is my working directory:
Down below is the location of my texture images
I tried adding a texture to a triangle however something seems to go wrong. When trying to run debug there is no error and no warning however it shows an grey window with no triangle and no texture whatsoever. Here is a part of my code, what is wrong?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f,0.0f
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f,0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] =
{
0,1,2,
1,2,3
};
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
//initializeaza buffer-ele de culoare si adancime inainte de a rasteriza cadrul curent
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//defineste culoarea de fundal
glClearColor(0.8, 0.8, 0.8, 1.0);
//specifica locatia si dimensiunea ferestrei
glViewport(0, 0, retina_width, retina_height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
//activeaza program shader-ul; apeluri ulterioare de rasterizare vor utiliza acest program
glUseProgram(shaderProgram); /**/
//activeaza VAO
glBindVertexArray(triangleVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//specifica tipul primitiei, indicele de inceput si numarul de indici utilizati pentru rasterizare
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawArrays(GL_TRIANGLES, 0, 3); /**/
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile(vertexShaderFileName);
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile(fragmentShaderFileName);
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glActiveTexture(GL_TEXTURE0);
glfwPollEvents();
renderScene();
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
glBindVertexArray(triangleVAO);
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
This is the fragment shader
#version 400
in vec3 colour;
in vec2 passTexture;
out vec4 fragmentColour;
uniform sampler2D dif;
void main() {
fragmentColour = texture(dif, passTexture);
}
This is the vertex shader:
#version 400
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 textcoord;
out vec3 colour;
out vec2 passTexture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
colour = vertexNormal;
passTexture = textcoord;
gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
}
By default all fields of the matrices in the vertex are shader are initialized by 0.0.
To make the code run you've to skip the matrices:
gl_Position = vec4(vertexPosition, 1.0);
Or initialize them by the Identity matrix in renderScene:
GLint model_loc = glGetUniformLocation(shaderProgram, "model");
GLint view_loc = glGetUniformLocation(shaderProgram, "view");
GLint proj_loc = glGetUniformLocation(shaderProgram, "projection");
GLint tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
Note, uniforms have to be set, after the program is installed by glUseProgram.
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
Since the Index buffers is stated in the Vertex Array Object, the VAO has to be bound, before the index buffer can be bound:
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
Set all the necessary states, and bind the necessary objects, before you do the draw call.
The viewport rectangle and the clear color should be set before glClear.
The texture should be bound before the mesh is drawn.
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
glUseProgram(shaderProgram);
// set the uniforms as described above
// [...]
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
Furthermore there is missing a comma (,) int the 2nd row of the array of vertex array attributes and the indices do not form a quad. Change it:
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
Finally, if you want to use mipmaping, then the texture minification filter has to be one of GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR.
Full code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
GLuint texture;
GLint model_loc, view_loc, proj_loc, tex_loc;
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile( vertexShaderFileName );
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile( fragmentShaderFileName );
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
model_loc = glGetUniformLocation(shaderProgram, "model");
view_loc = glGetUniformLocation(shaderProgram, "view");
proj_loc = glGetUniformLocation(shaderProgram, "projection");
tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("SOIL2/res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
You need to bind the vertex array object before you bind the index buffer, so you need to swap this around.
Edit: The vertex array bind needs to go above
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
as well.
Using OpenGL core profile, I'm trying to create a texture that fills the screen and displays a white square in the middle of the texture.
#include <SDL2/SDL.h>
#include "glad/glad.h"
#define SIMPLE_VERTEX_SHADER "#version 330 core \n \
layout (location = 0) in vec3 aPos; \n \
layout (location = 1) in vec2 aTexCoord; \n \
out vec2 TexCoord; \n \
void main() { \n \
gl_Position = vec4(aPos, 1.0f); \n \
TexCoord = vec2(aTexCoord.x, aTexCoord.y); \n \
}\n\0"
#define SIMPLE_FRAGMENT_SHADER "#version 330 core \n \
out vec4 FragColor; \n \
in vec3 ourColor; \n \
in vec2 TexCoord; \n \
uniform sampler2D tex; \n \
void main() { \n \
FragColor = texture(tex, TexCoord); \n \
}\n\0"
int main(int argv, char** args) {
SDL_Window *window;
SDL_GLContext glcontext;
if (SDL_Init(SDL_INIT_VIDEO)) {
printf("Unable to initialise SDL: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
int screen_width, screen_height;
screen_height = screen_width = 500;
window = SDL_CreateWindow("Texture Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!window) {
printf("Unable to create window: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
glcontext = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1);
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
{
printf("Failed to initialize GLAD\n");
}
const GLchar* vertexShaderSource = SIMPLE_VERTEX_SHADER;
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
const GLchar* fragmentShaderSource = SIMPLE_FRAGMENT_SHADER;
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
GLuint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLfloat vertices[] = {
1.0f, 1.0f, 0.0f, 1.0, 0.0f,
1.0f, -1.0f, 0.0f, 1.0, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0, 0.0f
};
GLfloat indices[] = {
0, 1, 3,
1, 2, 3
};
bool running;
running = true;
GLuint VAO, VBO, EBO;
SDL_Surface* surface;
SDL_Event e;
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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture);
surface = SDL_CreateRGBSurface(0, screen_width, screen_height, 32, 0, 0, 0, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
while(running) {
while(SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
running = false;
}
if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_ESCAPE:
running = false;
break;
default:
break;
}
}
}
if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface);
}
uint8_t* pixel_data = (uint8_t*)surface->pixels;
for (int y = screen_height * 0.25; y < screen_height * 0.75; ++y) {
for (int x = screen_width * 0.25; x < screen_width * 0.75; ++x) {
pixel_data[4 * (y * surface -> w + x) + 0] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 1] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 2] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 3] = 0xFF;
}
}
if (SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glUseProgram(0);
SDL_GL_SwapWindow(window) ;
}
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
It displays a white screen when it opens (as though I set the clear colour to white), and then it changes to a black screen almost immediately, and then stays like that.
I'm clearly doing something wrong, but I cannot work out. I get the feeling that my shaders are the problem. But I don't know for sure.
Is someone able to give me a pointer on what I'm doing wrong?
Thanks.
Indices defined as
GLfloat indices[] = {
0, 1, 3,
1, 2, 3
};
However, indices must be integer. Later when drawing it is said indices are GLuint:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
And float bits are interpreted as uint, giving invalid values like 1065353216, 1077936128, ..., which greatly exceeds vertex buffer size.
Define indices as GLuint (or uint32_t).
I am adding an answer based on keltar's answer in the comment to take this question out of the unanswered tab. If keltar answers I will delete my answer.
The issue is that the vertex attributes are qualified as floats in the lines:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
But the texture is expecting unsigned bytes:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
So changing the vertex attributes fixes the problem.
I've bee playing around again with Modern OpenGL (4.1) and was everything fine until I stepped into shading realms.
But before I even render something with shading I got some problems with the vertex shader.
The program is really simple, it simply reads an OBJ file and also the texture of the mesh. I put those things in their respective buffers and then draw it. At first it was drawing everything perfectly, but then I added 2 more uniform variable in the vertex shader and BAM! Nothing gets drawn. Funny thing is: as soon as I comment one of the extra uniforms, everything gets rendered again.
I really don't understand what is happening here, I thought I was extrapolating any limit of uniforms, but it is just 3 mat4 uniforms, and from what I googled, I have at least 1024 [source].
Anyway, I'm out of ideas, out of google query, so I come here to your help.
Thanks in advance!!
Ah, I'm using MacOSX El Captain and some information of the environment (got from glGetString):
Version: 4.1 ATI-1.40.16
Renderer: AMD Radeon HD 6750M OpenGL Engine
Some of the code not include is just Context creation and Shader compiling.
Note that if I delete uniform mat4 mM; it works perfectly. Otherwise, it keeps printing "Location -> -1" (saying it cannot find any uniform).
I really don't know what's going on.
P.S.: Also please don't mind for the terrible code, still trying to figure out some stuff code still not good.
vertexShader.gs:
#version 410
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec2 vTex;
out vec2 texCoord;
uniform mat4 mM;
uniform mat4 mV;
uniform mat4 mvp;
void main () {
texCoord = vTex;
gl_Position = mvp * vec4(vPosition, 1.0f);
}
Main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <OpenGl/gl.h>
//#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "picg.h"
#include "shader.h"
#include "tiny_obj_loader.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void matrices(GLfloat xAngle, GLfloat yAngle);
glm::mat4 projection, view, model, rotations;
glm::mat4 mvp;
glm::vec3 light;
GLuint vao, vbo, ibo, tbo;
GLuint texture;
GLuint shaderProgram;
const GLfloat angle = 1.0f;
GLfloat cYAngle;
GLfloat cXAngle;
GLfloat scale = 1.0f;
GLfloat points[] = {
-0.7f, +0.7f, +0.7f,
-0.7f, -0.7f, +0.7f,
+0.7f, -0.7f, +0.7f,
+0.7f, +0.7f, +0.7f
};
GLuint indices[] = {
0, 1, 2, 3, 0, 2
};
int main() {
GLFWwindow * window = create_context("Fish club", 600, 600);
initGL();
GLubyte vertexShader = shaderFromFile("vertexShader.gs", GL_VERTEX_SHADER);
GLubyte fragmentShader = shaderFromFile("fragmentShader.gs", GL_FRAGMENT_SHADER);
projection = glm::perspective(glm::radians(+45.f), 1024.f / 768.f, 0.1f, 600.0f);
view = glm::lookAt(
glm::vec3(+0.0f,+0.0f,+5.0f),
glm::vec3(+0.0f,+0.0f,+0.0f),
glm::vec3(+0.0f,+1.0f,+0.0f)
);
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(90.0f));
mvp = projection * view * model;
light = glm::vec3(0.0f, 1.0f, 1.0f);
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string err;
if (!tinyobj::LoadObj(shapes, materials, err, "res/GOLDFISH.obj")) {
throw std::runtime_error(std::string("Error loading OBJ file:\n") + err);
}
std::cout << "Shapes: " << shapes.size() << std::endl
<< "Materials: " << materials.size() << std::endl
<< "Positions: " << shapes[0].mesh.positions.size() << std::endl
<< "Normals: " << shapes[0].mesh.normals.size() << std::endl
<< "TexCoords: " << shapes[0].mesh.texcoords.size() << std::endl;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
int width, height, numComponents;
unsigned char * imageData = stbi_load("res/GOLDFISH.bmp",
&width, &height, &numComponents, 4);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
imageData);
glBindTexture(GL_TEXTURE_2D, NULL);
stbi_image_free(imageData);
GLsizei vertex_buffer_size = 0;
for (int i = 0 ; i < shapes.size(); ++i) {
vertex_buffer_size += sizeof(float) * shapes[i].mesh.positions.size();
}
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ARRAY_BUFFER, offset,
sizeof(float) * shapes[i].mesh.positions.size(),
&shapes[i].mesh.positions[0]);
offset += sizeof(float) * shapes[i].mesh.positions.size();
}
glBindBuffer(GL_ARRAY_BUFFER, NULL);
GLsizei index_buffer_size = 0;
GLsizei index_size = 0;
for (int i = 0 ; i < shapes.size() ; ++i) {
index_buffer_size += sizeof(float) * shapes[i].mesh.indices.size();
index_size += shapes[i].mesh.indices.size();
}
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset,
sizeof(unsigned int) * shapes[i].mesh.indices.size(),
&shapes[i].mesh.indices[0]);
offset += sizeof(unsigned int) * shapes[i].mesh.indices.size();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
GLsizei texcoord_buffer_size = 0;
for (int i = 0 ; i < shapes.size() ; ++i) {
texcoord_buffer_size += sizeof(float) * shapes[i].mesh.texcoords.size();
}
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, texcoord_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ARRAY_BUFFER, offset,
sizeof(float) * shapes[i].mesh.texcoords.size(),
&shapes[i].mesh.texcoords[0]);
offset += sizeof(float) * shapes[i].mesh.texcoords.size();
}
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindVertexArray(NULL);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cYAngle += 0.1f;
matrices(cXAngle, cYAngle);
glUseProgram(shaderProgram);
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mV") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mM") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mvp") << std::endl;
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mvp"),
1, GL_FALSE, &mvp[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mV"),
1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mM"),
1, GL_FALSE, &model[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, index_buffer_size, GL_UNSIGNED_INT, NULL);
glBindVertexArray(NULL);
glUseProgram(NULL);
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
void matrices(GLfloat xAngle, GLfloat yAngle) {
model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(xAngle), glm::vec3(+1.0f, +0.0f, +0.0f));
model = glm::rotate(model, glm::radians(yAngle), glm::vec3(+0.0f, +1.0f, +0.0f));
model = glm::scale(model, glm::vec3(40.0f));
mvp = projection * view * model;
}
edit:
As suggested I tried the following vertex shader:
#version 410
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec2 vTex;
out vec2 texCoord;
uniform mat4 mM;
uniform mat4 mV;
uniform mat4 mP;
void main () {
texCoord = vTex;
gl_Position = mP * mV * mM * vec4(vPosition, 1.0f);
}
And changed the following lines
glUseProgram(shaderProgram);
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mP") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mV") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mM") << std::endl;
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mP"),
1, GL_FALSE, &projection[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mV"),
1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mM"),
1, GL_FALSE, &model[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, index_buffer_size, GL_UNSIGNED_INT, NULL);
glBindVertexArray(NULL);
glUseProgram(NULL);
And still, I can see nothing and it only returns "Location -> -1" for every uniform.
mM and mV is not used in your vertex shader code. I believe it will be removed during compilation so when you try to get their location with glGetUniformLocation() this information is not available. Try to do something with mM and mV in your shader code.