Related
I am trying to render a texture with OpenGL. The texture I am using as a test is a bunch of black rectangles on a white background, as follows:
However, when rendering, the texture seem to be duplicated and overlayed multiple times on top of itself:
I set the scene up using:
std::string vertexSource = ShaderLoader::load("vertexSource.vert");
const char* vsource = vertexSource.c_str();
std::string fragmentSource = ShaderLoader::load("fragmentSource.frag");
const char* fsource = fragmentSource.c_str();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vsource, NULL);
glCompileShader(vertexShader);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fsource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
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, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1,2,GL_FLOAT, GL_FALSE, 2* sizeof(float), (void*)(sizeof(float)*12));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned char* data = stbi_load("image.png", &width, &height,&nrOfChannels, 0);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free((void *) data);
My render code is:
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, textureId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
My vertex shader is:
#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
out vec2 TextureCoordinate;
void main()
{
gl_Position = vec4( inVertex, 1 );
TextureCoordinate = inTexture;
}
and my fragment shader is:
#version 330 core
out vec4 FragColor;
in vec2 TextureCoordinate;
uniform sampler2D Texture;
void main() {
FragColor = texture(Texture,TextureCoordinate);
}
When an image with 3 channels (GL_RGB) is loaded to a texture object, GL_UNPACK_ALIGNMENT needs to be set to 1. By default GL_UNPACK_ALIGNMENT is 4, so each line of an image is assumed to be aligned to 4 bytes. The pixels in the buffer have a size of 3 bytes and are tightly packed, this would cause a misalignment.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // default
Since the image format is PNG, it is very likely that the image has 4 channels (GL_RGBA). Evaluate nrOfChannels before specifying the texture image:
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, 0);
// [...]
unsigned int format = nrOfChannels == 4 ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
It is also possible to force stbi_load to generate an image with 4 channels, by explicitly pass 4 to the last parameter:
int reqChannels= 4;
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, reqChannels);
// [...]
glTexImage2D(GL_TEXTURE_2D, GL_RGBA, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
I am trying to render a texture with OpenGL. The texture I am using as a test is a bunch of black rectangles on a white background, as follows:
However, when rendering, the texture seem to be duplicated and overlayed multiple times on top of itself:
I set the scene up using:
std::string vertexSource = ShaderLoader::load("vertexSource.vert");
const char* vsource = vertexSource.c_str();
std::string fragmentSource = ShaderLoader::load("fragmentSource.frag");
const char* fsource = fragmentSource.c_str();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vsource, NULL);
glCompileShader(vertexShader);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fsource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
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, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1,2,GL_FLOAT, GL_FALSE, 2* sizeof(float), (void*)(sizeof(float)*12));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned char* data = stbi_load("image.png", &width, &height,&nrOfChannels, 0);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free((void *) data);
My render code is:
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, textureId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
My vertex shader is:
#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
out vec2 TextureCoordinate;
void main()
{
gl_Position = vec4( inVertex, 1 );
TextureCoordinate = inTexture;
}
and my fragment shader is:
#version 330 core
out vec4 FragColor;
in vec2 TextureCoordinate;
uniform sampler2D Texture;
void main() {
FragColor = texture(Texture,TextureCoordinate);
}
When an image with 3 channels (GL_RGB) is loaded to a texture object, GL_UNPACK_ALIGNMENT needs to be set to 1. By default GL_UNPACK_ALIGNMENT is 4, so each line of an image is assumed to be aligned to 4 bytes. The pixels in the buffer have a size of 3 bytes and are tightly packed, this would cause a misalignment.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // default
Since the image format is PNG, it is very likely that the image has 4 channels (GL_RGBA). Evaluate nrOfChannels before specifying the texture image:
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, 0);
// [...]
unsigned int format = nrOfChannels == 4 ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
It is also possible to force stbi_load to generate an image with 4 channels, by explicitly pass 4 to the last parameter:
int reqChannels= 4;
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, reqChannels);
// [...]
glTexImage2D(GL_TEXTURE_2D, GL_RGBA, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
I'm trying to implement a background-blur effect with OpenGL.
Here is my thought:
drawing all background element to colorFBO
draw colorFBO into pingpongFBO[0] and pingpongFBO1
use pingpongFBO[0] as texture, draw hori-blur rect to pingpongFBO1
use pingpongFBO1 as texture, draw vert-blur rect to pingpongFBO[0]
Here is the result with blur radius of 200:
Result
As you can see, the hori-blur effect disappeared almost.
The edge of blue rectangle is still sharp.
If I only draw hori-blur part, it looks correct, the edge is now blurry.
Hori Only
Here is my blur frag shader code
#version 330 core
#define pow2(x)(x*x)
#define PI 3.14159265
uniform sampler2D screenTexture;
uniform bool horizontal;
uniform float radius;
out vec4 FragColor;
float gaussian(float x){
float sigma2=2.*pow2(radius/3.);
return(1./(sqrt(PI*sigma2)))*exp(-pow2(x)/sigma2);
}
void main(){
vec2 resolution=vec2(600,600);
vec2 uv=vec2(gl_FragCoord.xy/resolution);
vec4 color=vec4(0.);
float weight=gaussian(0);
color+=texture2D(screenTexture,uv)*weight;
float accum=weight;
if(horizontal){
for(int i=1;i<radius+1;i++){
vec2 off=vec2(i,0)/resolution;
weight=gaussian(i);
color+=texture2D(screenTexture,uv+off)*weight;
color+=texture2D(screenTexture,uv-off)*weight;
accum+=weight*2;
}
}else{
for(int i=1;i<radius+1;i++){
vec2 off=vec2(0,i)/resolution;
weight=gaussian(i);
color+=texture2D(screenTexture,uv+off)*weight;
color+=texture2D(screenTexture,uv-off)*weight;
accum+=weight*2;
}
}
FragColor=vec4((color/accum).xyz,1.);
}
Here is main CPP :
#include "Common.hh"
const unsigned int SCR_WIDTH = 600;
const unsigned int SCR_HEIGHT = 600;
float left = 150;
float top = 200;
float radius = 200;
void processInput(GLFWwindow *window);
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
float *quad1Vertices = rectWithSize(SCR_WIDTH, 200);
float *quad2Vertices = rectWithSize(200, SCR_WIDTH);
float *blurQuadVertices = rectWithSize(200.0, 200.0);
float backgroundVertices[] = {
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f};
unsigned int quad1VAO, quad1VBO;
glGenVertexArrays(1, &quad1VAO);
glGenBuffers(1, &quad1VBO);
glBindVertexArray(quad1VAO);
glBindBuffer(GL_ARRAY_BUFFER, quad1VBO);
glBufferData(GL_ARRAY_BUFFER, RECT_SIZE, quad1Vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
unsigned int quad2VAO, quad2VBO;
glGenVertexArrays(1, &quad2VAO);
glGenBuffers(1, &quad2VBO);
glBindVertexArray(quad2VAO);
glBindBuffer(GL_ARRAY_BUFFER, quad2VBO);
glBufferData(GL_ARRAY_BUFFER, RECT_SIZE, quad2Vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
unsigned int quad3VAO, quad3VBO;
glGenVertexArrays(1, &quad3VAO);
glGenBuffers(1, &quad3VBO);
glBindVertexArray(quad3VAO);
glBindBuffer(GL_ARRAY_BUFFER, quad3VBO);
glBufferData(GL_ARRAY_BUFFER, RECT_SIZE, blurQuadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
unsigned int backgroundVAO, backgroundVBO;
glGenVertexArrays(1, &backgroundVAO);
glGenBuffers(1, &backgroundVBO);
glBindVertexArray(backgroundVAO);
glBindBuffer(GL_ARRAY_BUFFER, backgroundVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(backgroundVertices), &backgroundVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float)));
Shader shader("simple_rect.vs", "simple_rect.fs");
Shader screenShader("screen.vs", "screen.fs");
Shader blurShader("blur_rect.vs", "blur_rect.fs");
glm::mat4 projection = glm::ortho(0.0f, (float)SCR_WIDTH, 0.0f, (float)SCR_HEIGHT, -1.0f, 1.0f);
glm::mat4 model = glm::mat4(1.0);
shader.use();
shader.setMat4("projection", projection);
blurShader.use();
blurShader.setMat4("projection", projection);
blurShader.setInt("screenTexture", 0);
screenShader.use();
screenShader.setMat4("projection", glm::mat4(1.0));
screenShader.setMat4("model", glm::mat4(1.0));
screenShader.setInt("screenTexture", 0);
GLuint colorFBO;
GLuint colorBuffer;
glGenFramebuffers(1, &colorFBO);
glGenTextures(1, &colorBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, colorFBO);
glBindTexture(GL_TEXTURE_2D, colorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
GLuint pingPongFBO[2];
GLuint pingPongColorBuffer[2];
glGenFramebuffers(2, pingPongFBO);
glGenTextures(2, pingPongColorBuffer);
for (GLuint i = 0; i < 2; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, pingPongFBO[i]);
glBindTexture(GL_TEXTURE_2D, pingPongColorBuffer[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingPongColorBuffer[i], 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glBindFramebuffer(GL_FRAMEBUFFER, colorFBO);
glClearColor(229.0 / 255.0, 229.0 / 255.0, 229.0 / 255.0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shader.use();
shader.setMat4("model", glm::translate(model, glm::vec3(0.0f, 100.0f, 0.0f)));
shader.setVec4("uColor", glm::vec4(0.3451, 0.7333, 0.2, 1.0));
glBindVertexArray(quad1VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
shader.setVec4("uColor", glm::vec4(0, 178.0 / 255.0, 1, 1.0));
shader.setMat4("model", glm::translate(model, glm::vec3(50.0f, 0.0f, 0.0f)));
glBindVertexArray(quad2VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, pingPongFBO[0]);
glBindTexture(GL_TEXTURE_2D, colorBuffer);
glClearColor(0.0f, 1.0f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(backgroundVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, pingPongFBO[1]);
glBindTexture(GL_TEXTURE_2D, colorBuffer);
glClearColor(0.0f, 1.0f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(backgroundVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, pingPongFBO[1]);
glBindTexture(GL_TEXTURE_2D, pingPongColorBuffer[0]);
blurShader.use();
blurShader.setMat4("model", glm::translate(model, glm::vec3(left, top, 0)));
blurShader.setInt("screenTexture", 0);
blurShader.setBool("horizontal", true);
blurShader.setFloat("radius", radius);
glBindVertexArray(quad3VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, pingPongFBO[0]);
glBindTexture(GL_TEXTURE_2D, pingPongColorBuffer[1]);
blurShader.setBool("horizontal", false);
glBindVertexArray(quad3VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.0f, 1.0f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(backgroundVAO);
glBindTexture(GL_TEXTURE_2D, pingPongColorBuffer[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &quad1VAO);
glDeleteBuffers(1, &quad1VBO);
glDeleteVertexArrays(1, &quad2VAO);
glDeleteBuffers(1, &quad2VBO);
glDeleteVertexArrays(1, &quad3VAO);
glDeleteBuffers(1, &quad3VBO);
glDeleteVertexArrays(1, &backgroundVAO);
glDeleteBuffers(1, &backgroundVBO);
glfwTerminate();
return 0;
}
The full source code is here
The vertical edge is blurry. But the effect is reduced and covered by the vertical blur in the 2nd pass. Note, the vertical blur reinforced the vertical edge, because it blurs along this edge.
After the 1st pass (horizontal blur), the main color on the left side is still blue and the main color on the right side is still green and white. The vertical blur, mix the colors along the columns of the image. That causes that the transition along the columns between the left (blue) and right (green/white) becomes a noticeable edge.
If you change the order of the passed (1st vertical blur, 2nd horizontal blur), then the horizontal edge becomes visible again:
In general the algorithm works. Compare the result, when a diagonal blur is used:
void main(){
// [...]
if(horizontal){
for(int i=1;i<radius+1;i++){
vec2 off=vec2(i,i)/resolution;
// [...]
}
}else{
for(int i=1;i<radius+1;i++){
vec2 off=vec2(-i,i)/resolution;
// [...]
}
}
// [...]
}
I am trying to add a texture onto my triangle but it just shows up as a black triangle. Here is my starting function that gets called:
GLuint vao;
GLuint shader_programme;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API createSimpleWindow()
{
if (std::this_thread::get_id() == MAIN_THREAD_ID)
{
oldContext = glfwGetCurrentContext();
newContext = glfwCreateWindow(640, 480, "window", NULL, oldContext);
glfwMakeContextCurrent(newContext);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
//triangle pts
float points[] = {
0.0f, 0.5f, 0.0f, 0.5f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f
};
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
glUseProgram(shader_programme);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height, nrComponents;
unsigned char *data = stbi_load("/Users/roma/Desktop/Escape Tech/BitBucketRepos/blankpluginGLFW/BlankPlugin/PluginSource/source/container2.png", &width, &height, &nrComponents, 0);
writeToLog("before data");
if (data) {
writeToLog("data contained!!!!!!");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
glUniform1i(glGetUniformLocation(shader_programme, "texture1"), 0);
//glfwCreateWindow(640, 480, "My Title", NULL, NULL);
glfwSetKeyCallback(newContext, key_callback);
}
else
{
writeToLog("not main thread");
}
}
Here is the function that gets called in a while loop:
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API windowMainLoop()
{
writeToLog("render loop");
glfwMakeContextCurrent(newContext);
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
// loop until the window closed
if (!glfwWindowShouldClose(newContext)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (std::this_thread::get_id() == MAIN_THREAD_ID)
{
// bind Texture
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(shader_programme);
glBindVertexArray(vao);
// draw points 0-3 from the currently bound VAO with current in-use shader
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(newContext);
// poll the events
glfwPollEvents();
}
//switch back to old context
glfwMakeContextCurrent(oldContext);
writeToLog("finished render loop");
}
}
My "if (data)" statement results in the text begin written to the log so I know the image is being loaded properly but I cannot figure out why the triangle is black.
Any help would be greatly appreciated!
The issue is the setup arrays of generic vertex attribute data. Each attribute tuple consist of 5 components (x, y, z, u, v):
float points[] = {
0.0f, 0.5f, 0.0f, 0.5f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f
};
So the stride parameter has to be 5 * siezof(GLfloat) rather than 6 * siezof(GLfloat):
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
The 2nd parameter of glBufferData is the size of the buffer in bytes. Your buffer consists of 15 (5 * 3) elements of type GLfloat. So the size is 15 * sizeof(float) rather than 9 * sizeof(float):
glBufferData(GL_ARRAY_BUFFER, 15 * sizeof(float), points, GL_STATIC_DRAW);
Since the format of the file is .png the last parameter of stbi_load should be set 4, to ensure that a 4 channels of the texture are get:
unsigned char *data = stbi_load("?.png", &width, &height, &nrComponents, 4);
The format and internal format of glTexImage2D have to be GL_RGBA.
By default the texture minifying function (GL_TEXTURE_MIN_FILTER) is GL_NEAREST_MIPMAP_LINEAR (see glTexParameteri). Since you don't use mip mapping, the parameter has to be changed to GL_LINEAR:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
I'm trying to render an image, but when the program runs, I get distorted lines for both triangles making up the quad:
init()
GLfloat vertexData[] = // Counter Clockwise
{
-0.5f, 0.5f, 0.0f, // V0 : Top Left
-0.5f, -0.5f, 0.0f, // V1 : Bottom Left
0.5f, -0.5f, 0.0f, // v2 : Bottom Right
0.5f, 0.5f, 0.0f // v3 : Top Right
};
GLint indexData[] =
{
0, 2, 3,
2, 0, 1
};
GLfloat textureCoords[] =
{
0, 0,
0, 1,
1, 1,
0, 0
};
int vSize = (sizeof(vertexData) / sizeof(vertexData[0]));
int iSize = (sizeof(indexData) / sizeof(indexData[0]));
// VAO
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
// IBO
glGenBuffers(1, &iboID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iSize * sizeof(GLuint), indexData, GL_STATIC_DRAW);
// VBO
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vSize * sizeof(GLfloat), vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Texture
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_FreeSurface(surface);
_textureLoc = glGetUniformLocation(shader.getID(), "textureSampler");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(_textureLoc, 0);
And within draw()
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindVertexArray(vaoID);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);