I am trying to apply a texture to a basic triangle in opengl. The problem is my texture doesn't works, it only applies a weird color onto the triangle...
I already looked at the doc, and some youtube tutorials but I really can't make it work.
Here are some samples of the code:
Texture constructor -
Textures::Textures(const std::string& fileName)
{
int width, height, numComponents;
unsigned char * data = stbi_load(
fileName.c_str()
, &width
, &height
, &numComponents
, 0
);
if (data == NULL)
std::cerr << "Texture loading error: " << fileName << std::endl;
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_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);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (numComponents == 3)
glTexImage2D(
GL_TEXTURE_2D
, 0
, GL_RGB
, width
, height
, 0
, GL_RGB
, GL_UNSIGNED_BYTE
, data
);
else if(numComponents == 4)
glTexImage2D(
GL_TEXTURE_2D
, 0
, GL_RGBA
, width
, height
, 0
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
}
Mesh constructor -
Meshes::Meshes(Vertex* vertices, unsigned int numVertices)
{
m_drawCount = numVertices;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoord;
positions.reserve(numVertices);
texCoord.reserve(numVertices);
for (unsigned int i = 0; i < numVertices; ++i) {
positions.push_back( *vertices[i].getPos() );
texCoord.push_back( *vertices[i].getTexture() );
}
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(
GL_ARRAY_BUFFER
, positions.size() * sizeof(positions[0])
, &positions[0]
, GL_STATIC_DRAW
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXTURE_COORD_VB]);
glBufferData(
GL_ARRAY_BUFFER
, texCoord.size() * sizeof(texCoord[0])
, &texCoord[0]
, GL_STATIC_DRAW
);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Shader fragment -
#version 120
varying out vec4 diffuseColor;
varying vec2 texCoord0;
uniform sampler2D diffuse;
void main()
{
diffuseColor = texture2D(diffuse, texCoord0 );
}
Shader vertex -
#version 120
attribute vec3 position;
attribute vec2 texCoord;
varying vec2 texCoord0;
void main()
{
gl_Position.xyz = position;
gl_Position.w = 1;
texCoord0 = texCoord;
}
Here is the code on github so you can check it out by yourself: https://github.com/Kosta-Git/Pong/tree/master/Pong
Also I have another problem which is i can't even load the texture.jpg file (bricks.jpg works) but i guess it is due to it not being 512x512.
The issue is in the constructor of class Shaders. The shader program is not linked correctly, because m_shaders[0] is set twice, but m_shaders[1] is never set.
Related
I'm trying to make a skybox that can change with a button.
My solution for this is to bind my skyboxes and load my textures in the following way:
//SkyBox
GLuint skyboxVBO, skyboxVAO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid *)0);
// Load textures
vector<const GLchar*> facesN;
facesN.push_back("SkyBox/night/right.tga");
facesN.push_back("SkyBox/night/left.tga");
facesN.push_back("SkyBox/night/top.tga");
facesN.push_back("SkyBox/night/bottom.tga");
facesN.push_back("SkyBox/night/back.tga");
facesN.push_back("SkyBox/night/front.tga");
GLuint cubemapTextureN = TextureLoading::LoadCubemap(facesN);
vector<const GLchar*> faces;
faces.push_back("SkyBox/day/right.tga");
faces.push_back("SkyBox/day/left.tga");
faces.push_back("SkyBox/day/top.tga");
faces.push_back("SkyBox/day/bottom.tga");
faces.push_back("SkyBox/day/back.tga");
faces.push_back("SkyBox/day/front.tga");
GLuint cubemapTexture = TextureLoading::LoadCubemap(faces);
Then, in the program loop I draw the skybox with the following:
// Draw skybox as last
glDepthFunc(GL_LEQUAL); // Change depth function so depth test passes when values are equal to depth buffer's content
SkyBoxshader.Use();
view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // Remove any translation component of the view matrix
glUniformMatrix4fv(glGetUniformLocation(SkyBoxshader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(SkyBoxshader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
// skybox cube
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE1);
if (daytime == 1.0f) {
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
}
else {
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTextureN);
}
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS); // Set depth function back to default
In theory, whenever I press the button that changes the value of daytime, the skybox should change its textures to cubemapTextureN and, with another press of the button, change back to cubemapTexture. Instead, it just draws the texture that was loaded last, cubemapTexture in this case.
I already tested daytime and it does change, so it's not that.
Also, I tried loading cubemapTextureN after cubemapTexture and by doing so cubemapTextureN gets drawn instead, but still no change. I'm assuming somehow while loading the second textures, the first ones get updated, which shouldn't happen since they have different names, unless i'm understanding it wrong.
Easy solution would be to just make models of the entire skyboxes and work with that, but if possible I want to see if I can use this solution.
Edit:
These are the Shaders for the skybox.
Fragment shader:
#version 330 core
in vec3 TexCoords;
out vec4 color;
uniform samplerCube skybox;
void main()
{
color = texture(skybox, TexCoords);
}
Vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
out vec3 TexCoords;
uniform mat4 projection;
uniform mat4 view;
void main()
{
vec4 pos = projection * view * vec4(position, 1.0);
gl_Position = pos.xyww;
TexCoords = position;
}
And their use:
Shader SkyBoxshader("Shaders/SkyBox.vs", "Shaders/SkyBox.frag");
Also, if this is usefull, this is the header with the definition of TextureLoading, which contains LoadCubemap
#pragma once
// GLEW
#include <GL/glew.h>
// Other Libs
#include "stb_image.h"
// Other includes
#include "Model.h"
#include <vector>
class TextureLoading
{
public:
static GLuint LoadTexture(GLchar *path)
{
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
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);
stbi_image_free(data);
}
else
{
std::cout << "Failed to load texture" << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
static GLuint LoadCubemap(vector<const GLchar * > faces)
{
GLuint textureID;
glGenTextures(1, &textureID);
int width, height, nrChannels;
for (unsigned int i = 0; i < faces.size(); i++)
{
unsigned char *data = stbi_load(faces[i], &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
else
{
std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
return textureID;
}
};
I am a bloody newbie to OpenGL and it still looks sometimes like black magic to me. I just want to load and display an texture for testing purposes and I do not want to use the tutorial libraries to really understand what happens. But I just get a black screen and I cannot find the reason for it.
My c++ source code
int main(){
new cpp_logger();
GLint program_rgb_;
Mat img = imread("plane.jpg");
std::string file_path = "plane.jpg";
// Set viewport window size and clear color bit.
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//set viewport
glViewport(0, 0, img.size().width, img.size().height);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {-1, 1, -1, -1, 1, 1, 1, -1,
0, 0, 0, 1, 1, 0, 1, 1};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//create program and shader
program_rgb_ = glCreateProgram();
const char* vertexShader = read_shader("vertex.glsl"); //simple method to read the shader files
const char* fragmentShader = read_shader("fragment.glsl");
CreateShader(program_rgb_, GL_VERTEX_SHADER, vertexShader); //simple method to link and compile shader programs
CreateShader(program_rgb_, GL_FRAGMENT_SHADER, fragmentShader);
glLinkProgram(program_rgb_);
glUseProgram(program_rgb_);
//use fast 4-byte alignment (default anyway) if possible because using OpenCV
glPixelStorei(GL_UNPACK_ALIGNMENT, (img.step & 3) ? 1 : 4);
//set length of one complete row in data (doesn't need to equal image.cols)
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, img.step/img.elemSize());
flip(img, img, 0);
// Load texture
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//set parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data);
glUniform1i(glGetUniformLocation(program_rgb_,"tex"), 0);
uint8_t* result = new uint8_t[img.cols * img.rows * 4];
while(true){
GLint pos_location = glGetAttribLocation(program_rgb_, "a_position");
GLint tc_location = glGetAttribLocation(program_rgb_, "a_texCoord");
// Specify the layout of the vertex data
glEnableVertexAttribArray(pos_location);
glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
//specify color data
glEnableVertexAttribArray(tc_location);
glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, static_cast<float*>(0) + 8);
// Draw a rectangle from the 2 triangles using 6 indices
glDrawArrays(GL_TRIANGLES, 0, 8);
glReadPixels(0, 0, img.rows, img.cols, GL_BGRA_EXT, GL_UNSIGNED_BYTE, (void*)result);
auto result_ = cv::Mat(img.rows, img.cols, CV_8UC4, result);
imshow("img", result_);
if(waitKey(1) >= 0) break;
}
destroyAllWindows();
return EXIT_SUCCESS;
}
My fragment shader
#version 150 core
precision mediump float;
in vec2 texCoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = texture2D(tex, texCoord);
}
my vertex shader
#version 150 core
out vec2 texCoord;
attribute vec2 a_texCoord;
attribute vec4 a_position;
void main()
{
texCoord = a_texCoord;
gl_Position = a_position;
}
Thank you a lot for your help!
EDIT
Sorry for the missunderstanding. I meant: I do not want to use the libraries like SOIL and SFML and I want to go an alternative way to fully understand what actually happens.
I'm currently working in a deferred shading and I created a class which manages the FBOs and draw the buffers on the screen.
This is how it looks so far:
FBORender::FBORender(float screenWidth, float screenHeight) :
_screenWidth(screenWidth),
_screenHeight(screenHeight),
ProgramManager("defVertexShader.txt", "defFragShader.txt")
{
CreateProgram();
_vbo[0] = 0;
_vbo[1] = 0;
_vao = 0;
BuildQuad();
BuildVAO();
glGenFramebuffers(1, &_fbo);
glGenRenderbuffers(1, &_depthBuffer);
// Bind the depth buffer
glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, (int)_screenWidth, (int)_screenHeight);
// Generate and bind the texture for diffuse
glGenTextures(1, &_diffuseBuffer);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, 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);
// Generate and bind the texture for positions
glGenTextures(1, &_positionBuffer);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, 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);
// Generate and bind the texture for normals
glGenTextures(1, &_normalBuffer);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, 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);
// Bind the FBO so that the next operations will be bound to it.
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
// Attach the textures to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _diffuseBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _positionBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _normalBuffer, 0);
GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
printf("DeferredLighting::Init: FrameBuffer incomplete: 0x%x\n", fboStatus);
exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
FBORender::~FBORender()
{
glDeleteTextures(1, &_normalBuffer);
glDeleteTextures(1, &_positionBuffer);
glDeleteTextures(1, &_diffuseBuffer);
glDeleteFramebuffers(1, &_fbo);
glDeleteVertexArrays(1, &_vao);
glDeleteBuffers(2, _vbo);
}
void FBORender::Start()
{
// Bind the FBO and set the viewport to the proper size
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glViewport(0, 0, (int)_screenWidth, (int)_screenWidth);
// Clear the render targets
GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffClear);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffOpaque);
}
void FBORender::Draw(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_ModelViewProjection = Projection * ModelView;
_ModelView = ModelView;
glDisable(GL_DEPTH_TEST);
Bind();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glBindVertexArray(_vao);
LoadUniformVariables();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
UnBind();
}
void FBORender::Stop()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FBORender::BuildQuad()
{
_coordinates[0] = 1.0f;
_coordinates[1] = 1.0f;
_coordinates[2] = 0.0f;
_coordinates[3] = -1.0f;
_coordinates[4] = 1.0f;
_coordinates[5] = 0.0f;
_coordinates[6] = 1.0;
_coordinates[7] = -1.0f;
_coordinates[8] = 0.0f;
_coordinates[9] = -1.0f;
_coordinates[10] = -1.0f;
_coordinates[11] = 0.0f;
_uv[0] = 1.0f;
_uv[1] = 1.0f;
_uv[2] = 0.0f;
_uv[3] = 1.0f;
_uv[4] = 1.0f;
_uv[5] = 0.0f;
_uv[6] = 0.0f;
_uv[7] = 0.0f;
}
void FBORender::BuildVAO()
{
// Generate and bind the vertex array object
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate and bind the vertex buffer object
glGenBuffers(2, _vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), _coordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), _uv, GL_STATIC_DRAW);
LoadAttributeVariables();
glBindVertexArray(0);
}
void FBORender::LoadUniformVariables()
{
// OpenGL Matrices
GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvMatrix");
glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelView));
// Texture buffers
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
GLint Diffuse_location = glGetUniformLocation(GetProgramID(), "tDiffuse");
glUniform1i(Diffuse_location, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
GLint Position_location = glGetUniformLocation(GetProgramID(), "tPosition");
glUniform1i(Position_location, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
GLint Normal_location = glGetUniformLocation(GetProgramID(), "tNormals");
glUniform1i(Normal_location, 0);
}
void FBORender::LoadAttributeVariables()
{
// Vertex Attributes
GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
glEnableVertexAttribArray(VertexPosition_location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "uvCoord");
printf("%d \n", TextureCoord_Location);
glEnableVertexAttribArray(TextureCoord_Location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
And those are my shaders:
#version 410 core
uniform mat4 mvMatrix;
in vec4 vPosition;
in vec2 uvCoord;
smooth out vec2 texCoord;
void main(void)
{
texCoord = uvCoord;
gl_Position = vPosition * mvMatrix;
}
#version 410 core
uniform sampler2D tDiffuse;
uniform sampler2D tPosition;
uniform sampler2D tNormals;
in vec2 texCoord;
out vec4 fragColor;
void main( void )
{
vec4 image = texture( tDiffuse, texCoord.st );
vec4 position = texture( tPosition, texCoord.st );
vec4 normal = texture( tNormals, texCoord.st );
fragColor.xyz = vec3(0.5f, 0.5f, 0.5f);
}
The problems is that when I try to set the attribute variables the one called uvCoord is not found. I think this may be due to an optimization, however, if that's so, what am I'm doing wrong or how should I do it? The uvCoord is used in the fragment shader.
The uvCoord is used in the fragment shader.
No it is not. Your output is a constant color. As a result, the texture fetches before are all eliminated by a decent compiler, as is the texCoord varying. This ultimately results in the elimination of the input attribute, which simply does not affect the output of the program in any way. This is allowed by the GL spec. Your attribute is just not considered active, but only active attributes have locations.
I am trying to apply 1D texture to lines. It works but lines shimmer. I don't want this shimmering effect. Like on the picture.
I've also added a video about shimmering problem:
Shimmering Problem Video
How can I solve this problem? I am adding the codes below.
Vertex Shader:
attribute vec4 vertexMC;
uniform mat4 MCVCMatrix;
uniform mat4 VCDCMatrix;
attribute float tcoordMC;
varying float tcoordVC;
void main()
{
tcoordVC=(vertexMC.x+vertexMC.y+vertexMC.z)/3.0;
gl_Position=VCDCMatrix*MCVCMatrix*vertexMC;
}
Fragment Shader:
varying float tcoordVC;
uniform sampler1D texture1;
uniform vec3 GridColor;
void main()
{
gl_FragColor=vec4(GridColor, texture1D(texture1,tcoordVC).a);
if (gl_FragColor.a <= 0.0) discard;
}
Texture:
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture( GL_TEXTURE_1D, texture );
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
unsigned char buf[ 16 * 4 ];
for( size_t i=0; i < sizeof( buf ); i+=4 )
{
buf[ i+0 ]=255;
buf[ i+1 ]=0;
buf[ i+2 ]=0;
}
buf[3]= 255;
buf[7]= 0;
buf[11]=255;
buf[15]=0;
buf[19]=255;
buf[23]=0;
buf[27]=255;
buf[31]=0;
buf[35]=255;
buf[39]=0;
buf[43]=255;
buf[47]=0;
buf[51]=255;
buf[55]=0;
buf[59]=255;
buf[63]=0;
glTexImage1D( GL_TEXTURE_1D, 0, 4, sizeof( buf ) / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf );
InternalShader->Program.SetUniformi("texture1",1);
Draw Section:
glEnable( GL_TEXTURE_1D );
glBindTexture( GL_TEXTURE_1D, texture);
for(unsigned int i=0;i<GridsInternal.size();i++)
{
AGrid=GridsInternal[i];
if(!AGrid->GetActivity())
continue;
ACellBO=CellBOs[i];
AVBO=VBOs[i];
ALayout=Layouts[i];
AVBO->Bind();
SetMapperShaderParameters(i);
SetPropertyShaderParameters(i);
ACellBO->ibo.Bind();
glDrawRangeElements(GL_LINES, 0,
static_cast<GLuint>(ALayout->VertexCount-1),
static_cast<GLsizei>(ACellBO->indexCount),
GL_UNSIGNED_INT,
reinterpret_cast<const GLvoid *>(NULL));
AVBO->Release();
ACellBO->ibo.Release();
ACellBO->vao.Release();
}
glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_1D);
I have the following setup for basic texture mapping
void init(void) {
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[6][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.1, 0.1 }, // UVs
{ 0.9, 0.1 },
{ 0.1, 0.9 }
};
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint program = LoadShaders( "triangles.vert", "triangles.frag" );
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(1, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(2*3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
GLuint sloc = glGetUniformLocation(program, "mySampler");
glUniform1i(sloc, 0);
int x,y,n;
unsigned char *data = stbi_load("bricks.jpg", &x, &y, &n, 4);
glGenTextures(1, &m_textureId);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexParameterf(m_textureId, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(m_textureId, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}
Vertex Shader:
#version 330 core
layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec2 uv;
out vec2 texCoord;
void
main() {
gl_Position = vPosition;
texCoord = uv;
}
Fragment Shader:
#version 330 core
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D mySampler;
void
main() {
fColor = texture(mySampler, texCoord);
}
However, nothing is displayed on the screen. If I swap out my frag shader with one that just sets a static color, I see the triangle. I have confirmed that I am getting data from the image and printed out a sample set of RGBA data that looks correct (rgb vary, but alpha is constant 0xFF). I've read at least 5 tutorials but can't seem to get it right.
I've also confirmed that if I do:
fColor = vec4(texCoord.x, texCoord.y, 0.0, 1.0);
I get a gradient of colors which I believe tells me I'm getting correctly interpolated values of my UVs coming through.
Apparently these texparams are required for some implementations
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );