opengl texture - no access to the image - opengl

I am trying to get a simple triangle textured, but got no image on the screen.
By using another shader that uses the colors from a color buffer it works fine.
I checked the content of the bmp image before passing it to gl.
This is the part that loads and delivers the texture to gl
uv 0,0 / 1,0 / 0.5, 1.0
bmp_s = Load_BMP( tex_file );
glActiveTexture( GL_TEXTURE0 );
glGenTextures( 1, &tex_buf->texture ); // Create the buffer id
glBindTexture( GL_TEXTURE_2D, tex_buf->texture ); // bind it
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, bmp_s->width, bmp_s->height, 0, GL_BGR, GL_UNSIGNED_BYTE, bmp_s->img );
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_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glGenerateMipmap( GL_TEXTURE_2D );
this is the drawing loop
do
{
Process_Input_Events(); // get mouse & kb -- calc mvp / view matrix
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
_uid_mvp = glGetUniformLocation( __sh_list[ 3 ].prg_id, "mvp_mx" );
_uid_tex_sampler = glGetUniformLocation( __sh_list[ 3 ].prg_id, "tex_sampler" );
glUseProgram( sh_s->prg_id ); // use the shader
glUniformMatrix4fv( _uid_mvp, 1, GL_FALSE, &_sys.mvp_mx[ 0 ][ 0 ] ); // send mvp
glBindVertexArray( vao->id ); // bind vao
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, vao->tex_buf->texture );
glUniform1i( _uid_tex_sampler, 0 );
glDrawArrays( vao->prim, 0, vao->vx_b->numb );
glBindVertexArray( 0 ); // unbind vao
glUseProgram( 0 ); // unbind shader
} while( condition );
and here are the shaders
#version 450 core
layout( location = 0 ) in vec3 vx; // the vertex_buffer in modelspace
layout( location = 3 ) in vec2 uv_in; // uv coordiantes for each vertex
out vec2 uv;
uniform mat4 mvp_mx;
void main()
{
gl_Position = mvp_mx * vec4( vx, 1.0f );
uv = uv_in;
}
#version 450 core
in vec2 uv; // interpolated values from vertex shader
out vec3 out_color;
uniform sampler2D tex_sampler; // Index of opengl texture
void main()
{
out_color = texture( tex_sampler, uv ).rgb;
}
any help will be appreciated

Related

OpenGL/Glew C++ Texture not applying

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.

OpenGL - FBO black screen when rendering to texture on NVIDIA card

I've followed some tutorials on how to setup and render an FBO. At first it worked and the scene rendered fine, but it turns out the program was using the integrated GPU. (I'm using my laptop)
Then, out of curiosity, I ran it with the "higher-performance" GPU (an Nvidia GeForce GT540M) and the screen was all black. At this point I tried saving the FBO's color texture into a file and the scene was actually being drawn there.
But eventually I found a solution. Previously I would only clear the FBO (color and depth buffers), but now I clear both the FBO and the default framebuffer and the scene is rendered again.
So the question is, is it bad that I have to call glClear twice? Do I really have to call glClear twice? Why would the one clear work on the integrated card?
I can show some code if it helps.
Framebuffer initialization
bool FrameBufferObject::initializeFBO( int width, int height ) {
glActiveTexture( GL_TEXTURE0 );
if ( !_colorTexture.createEmptyTexture( width, height ) ) {
return false;
}
_textureId = _colorTexture.getTextureId();
if ( !_depthTexture.createDepthTexture( width, height ) ) {
return false;
}
_depthTextureId = _depthTexture.getTextureId();
glGenFramebuffers( 1, &_frameBufferID );
glBindFramebuffer( GL_FRAMEBUFFER, _frameBufferID );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureId, 0 );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTextureId, 0 );
if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) {
return false;
}
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
_width = width;
_height = height;
_isInitialized = true;
return true;
}
Color Texture
bool Texture::createEmptyTexture( int width, int height ) {
if ( isLoaded() ) {
closeTexture();
}
GLuint textureId = 0;
glGenTextures( 1, &textureId );
if ( getOpenGLError( "Unable to generate TextureID." ) ) {
return false;
}
glBindTexture( GL_TEXTURE_2D, textureId );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glBindTexture( GL_TEXTURE_2D, 0 );
if ( getOpenGLError( "Error creating empty texture." ) ) {
glDeleteTextures( 1, &textureId );
return false;
}
_isLoaded = true;
_textureWidth = _imageWidth = width;
_textureHeight = _imageHeight = height;
_textureId = textureId;
return true;
}
The Depth Texture is the same, except it uses the GL_DEPTH_COMPONENT format,
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
Post Processing Shader
Vertex shader
#version 330 core
in vec2 inVertex;
in vec2 inTexture;
out vec2 texCoords;
void main() {
texCoords = inTexture;
gl_Position = vec4( inVertex.x, inVertex.y, 0, 1 );
}
Fragment shader
#version 330 core
in vec2 texCoords;
uniform sampler2D texture0;
layout(location = 0) out vec4 outColor;
void main() {
vec4 color = texture( texture0, texCoords );
outColor = color;
}
The rendering code looks like this,
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
fbo.bindFBO();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// .. render scene ..
fbo.unbindFBO();
// This is a namespace
PostProcShader::shader.useShader();
PostProcShader::render( fbo.getColorTexture() );
PostProcShader::shader.disableShader();
SDL_GL_SwapWindow( window );
Where the post processing shader simply renders the texture on a screen-sized quad. The scene uses 3 shaders: one for 3D objects, the second for the skybox and last one for fonts.
I'm using C++, SDL2 and (of course) OpenGL/Glew in VS 2015.
Edit:
Depth Test initialization
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
glDepthFunc( GL_LEQUAL );
glDepthRange( 0.0f, 1.0f );
glClearDepth( 1.0f );
I got a similar problem when I went from Intel HUD to Nvidia. However my solution was simple. I had to ensure I called glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) before rendering to the new framebuffer (on Nvidia) otherwise I would see nothing rendered. I suspect that on Nvidia the depth buffer is not set to the same defaults as on Intel so clearing it sets it to the opengl default clear value.

How to make Image_load_store work (reading from image in pixel shader)

I'm writing Win32 app using https://www.opengl.org/wiki/Image_Load_Store - I want to read a value from the texture attached to Pixel shader (and once it's working, I will change operation to write). I'm using GLFW and GLEW, the supported OGL version of my gfx card is 4.2. The relevant texture setup code looks like this:
typedef unsigned int BufferType;
int buf_w = 3;
int buf_h = 3;
int buf_size = buf_w * buf_h;
BufferType * bufferCounter = new BufferType[buf_size];
for (int i = 0; i < buf_size; ++i)
bufferCounter[i] = 200;
glActiveTexture( GL_TEXTURE0 );
glEnable( GL_TEXTURE_2D );
glGenTextures( 1, &tex2d );
glBindTexture( GL_TEXTURE_2D, tex2d );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0 );
glTexImage2D( GL_TEXTURE_2D, 0, GL_R32UI, buf_w, buf_h, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, bufferCounter );
Main loop:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
glBindTexture( GL_TEXTURE_2D, tex2d );
glBindImageTexture( 0, tex2d, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI ); // bind 2d tex to read_tex
glDrawArrays(GL_TRIANGLES, 0, 3);
Vertex shader is irrelevant, just gl_Position = vec4 (vertex_position, 1.0); Fragment shader:
#version 430
#extension ARB_shader_image_load_store : enable
in vec3 color;
out vec4 frag_color;
readonly layout(r8ui) uniform uimage2D read_tex;
void main()
{
frag_color = imageLoad(read_tex, ivec2(0,0) ); // read from attached tex
}
I check with glGetError - no errors. Also shaders compile and link. The triangle isn't visible on the screen (but if I set color to constant, it is). Any ideas on what might be wrong? I tried using in main loop functions loc = glGetUniformLocation( shader_program, "read_tex" ); glUniform1i( loc, tex2d ); but they didn't help. Thank you for help. Unfortunately I couldn't find any example on how to use this OGL functionality, and the documentation is scarce.

opengl - Only one texture displaying

I have been trying draw a hut (as a cylinder with a cone on top) and add a brick txture to the wall and a roof-tile texture to the roof. However, I am only getting the first texture that I load (the bricks).
Here is my code (Please note that I have tried to switch between textures using glActiveTexture):
void drawCylinder()
{
int width, height;
unsigned char * data_for_wall = SOIL_load_image("./bricks.jpg", &width, &height, NULL, 0);
glDisable(GL_LIGHTING);
glGenTextures( 2, textures );
glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Generate mipmaps, by the way.
glGenerateMipmap(GL_TEXTURE_2D);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB, GL_UNSIGNED_BYTE, data_for_wall);
for(float theta = 0.0; theta <= 360.0; theta += 10.0 )
{
//colors[k] = color4(0.69, 0.35, 0.0, 1.0); //This color is brown.
tex_coords[global_index]=vec2(theta*DegreesToRadians, 0.0);
float x = 0.15*sin(theta*DegreesToRadians);
float y = 0.15*cos(theta*DegreesToRadians);
points[global_index] = Translate(0.6, 0.0, 0.35)*point4(x, 0.0, y, 1.0);
// This is the
// bottom of the cylinder. The points are plotted in a full circle. The first three numbers are the x,y and z values
// respectively. The last number (ie. 1.0) is not important - it just converts to homogeneous coordinates.
++global_index;
tex_coords[global_index] = vec2(theta*DegreesToRadians, 0.25);
points[global_index] = Translate(0.6, 0.0, 0.35)*point4(x, 0.25, y, 1.0);
// This is the
// top of the cylinder
++global_index;
}
}
//The roof of the hut
void drawCone()
{
int width, height;
unsigned char * data_for_roof = SOIL_load_image("./roof_tiles.jpg", &width, &height, NULL, 0);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glBindTexture( GL_TEXTURE_2D, textures[1] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Generate mipmaps, by the way.
glGenerateMipmap(GL_TEXTURE_2D);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB, GL_UNSIGNED_BYTE, data_for_roof);
int index = 0;
int l = 0;
for(float theta = 0.0; theta <= 360.0; theta += 10.0)
{
tex_coords[global_index]=vec2(theta*DegreesToRadians, 0.25);
points[global_index] = Translate(0.6, 0.0, 0.35)*point4(0.0, 0.5, 0.0, 1.0); // This is the top of the cone.
++global_index;
tex_coords[global_index] = vec2(theta*DegreesToRadians, 0.5);
points[global_index] = Translate(0.6, 0.0, 0.35)*point4(0.25*sin(theta*DegreesToRadians), 0.25, 0.25*cos(theta*DegreesToRadians), 1.0);
// This is the
// bottom of the cone.
++global_index;
}
}
And here is the display function:
void
display( void )
{
mat4 mv = Translate(0.0, -0.065, -rad)*RotateX(Theta[0])*RotateY(Theta[1])*RotateZ(Theta[2]);
mat4 p = Perspective(10.0, aspectRatio, zNear, zFar);
glUniformMatrix4fv( matrix_loc, 1, GL_TRUE, mv );
glUniformMatrix4fv( projection_loc, 1, GL_TRUE, p );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glDrawArrays( GL_TRIANGLE_STRIP, 0, 74 );
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glDrawArrays( GL_TRIANGLE_STRIP, 74, 74);
glutSwapBuffers();
}
I am not sure if it is important to include the fragment shader but I will do it anyways:
#version 150
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D texture;
void main()
{
fColor = texture2D( texture, texCoord );
}
I have been struggling for hours to get this right. Does anyone know what I have done wrong?
glActiveTexture() is used to set the texture slot that you are binding a texture to when multi-texturing (rendering more than one texture in a single pass). For example, you might have one texture for a texture map, another for normal map and so on.
However, you are not multi-texturing, because you render the walls and the cone in separate passes (i.e. two separate calls to glDrawArrays()), and your shader only uses a single texture per pass. So within each pass you are only rendering a single texture, which will be in slot 0.
If you set the active texture to GL_TEXTURE1 and then call glBindTexture() then the texture will be bound to slot 1, and slot 0 will remain unchanged.
So, set the active texture slot to 0 both times. Remove this line from your display() function:
glActiveTexture(GL_TEXTURE1);

Unwanted Shimmering Effect with 1D Texture on Lines

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);