2

I'm using the tutorials on http://arcsynthesis.org/gltut/ to learn OpenGL, it's required, I have to use it. Mostly I want to apply the textures from Tutorial 15 onto objects in tutorial 7 (world with UBO).

For now it seemed like the textures only work when mipmaps are turned on. This comes with a downside: The only mipmap used is the one with an index of zero, and that's the 1 colored 1x1 pixel one. I tried setting the minimum level of a mipmap higher or turning off mipmaps entirely, but even that doesn't fix thing, because then everything turns pitch black. Now I'll list the most important parts of my program

EDIT: I guess I'll add more details...

The vertex shader has something like this:

#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec3 normal;
//Added these later 
layout(location = 5) in vec2 texCoord;
out vec2 colorCoord;

smooth out vec4 interpColor;
out vec3 vertexNormal;
out vec3 modelSpacePosition;
out vec3 cameraSpacePosition;

uniform mat4 worldToCameraMatrix;
uniform mat4 modelToWorldMatrix;
uniform mat3 normalModelToCameraMatrix;
uniform vec3 dirToLight;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;
uniform vec4 baseColor;

uniform mat4 cameraToClipMatrix;

void main()
{
vertexNormal = normal;
vec3 normCamSpace = normalize(normalModelToCameraMatrix * vertexNormal);
cameraSpacePosition = normCamSpace;

float cosAngIncidence = dot(normCamSpace, dirToLight);
cosAngIncidence = clamp(cosAngIncidence, 0, 1);
modelSpacePosition.x = position.x;
modelSpacePosition.y = position.y;
modelSpacePosition.z = position.z;

vec4 temp = modelToWorldMatrix * position;
temp = worldToCameraMatrix * temp;
gl_Position = cameraToClipMatrix * temp;

interpColor = ((lightIntensity * cosAngIncidence) + (ambientIntensity)) * baseColor;
colorCoord= texCoord ;
}

The fragment shader like this:

#version 330
in vec3 vertexNormal;
in vec3 modelSpacePosition;

smooth in vec4 interpColor;

uniform vec3 modelSpaceLightPos;
uniform vec4 lightIntensity2;
uniform vec4 ambientIntensity2;

out vec4 outputColor;

//Added later
in vec2 colorCoord;
uniform sampler2D colorTexture;


void main()
{
vec3 lightDir2 = normalize(modelSpacePosition - modelSpaceLightPos);

float cosAngIncidence2 = dot(normalize(vertexNormal), lightDir2);
cosAngIncidence2 = clamp(cosAngIncidence2, 0,  1);

float light2DistanceSqr = dot(modelSpacePosition - modelSpaceLightPos, modelSpacePosition - modelSpaceLightPos);

//added
vec4 texture2 = texture(colorTexture, colorCoord);

outputColor = ((ambientIntensity2 + (interpColor*2))/4) + 
((((interpColor) * lightIntensity2/200 * cosAngIncidence2) + (ambientIntensity2* interpColor )) 
/( ( sqrt(light2DistanceSqr) + light2DistanceSqr)/200 ));
//No outputColor for texture testing
outputColor =  texture2 ; 

}
}

Those were both shaders. And here are the parts added to the .cpp:

#include <glimg/glimg.h>
#include "../framework/directories.h"     
[...]
const int g_colorTexUnit = 0;
GLuint g_checkerTexture = 0;

And here's the loader for the texture:

void LoadCheckerTexture()
{
try

{
std::string filename(LOCAL_FILE_DIR);
filename += "checker.dds";
std::auto_ptr<glimg::ImageSet>
 pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));

glGenTextures(1, &g_checkerTexture);
glBindTexture(GL_TEXTURE_2D, g_checkerTexture);

glimg::SingleImage image = pImageSet->GetImage(0, 0, 0);
glimg::Dimensions dims = image.GetDimensions();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image.GetImageData());

glBindTexture(GL_TEXTURE_2D, 0);
}
catch(std::exception &e)
{
printf("%s\n", e.what());
throw;
}
}

Naturally I've got this in void init():

LoadCheckerTexture();

And then when rendering the object:

glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
glBindTexture(GL_TEXTURE_2D,g_checkerTexture);
g_pLeftMesh->Render();
glBindSampler(g_colorTexUnit, 0);
glBindTexture(GL_TEXTURE_2D, 0);

With all of this, I get put pitch black for everything, however when I change the outputColor equation into "texture + outputColor;", everything looks normal. I have no idea what I'm doing wrong here. A friend tried to help me, we removed some unnecessairy stuff, but we got nothing running.

Jan Nowak
  • 45
  • 1
  • 7
  • 1
    what is this line at the end: glBindSampler(g_colorTexUnit, 0);... maybe it should be glActiveTexture ? Second thing: did you set the uniform in the shader: glUniform1i("colorTexture", g_colorTexUnit) ? – fen Sep 05 '13 at 14:18
  • 1
    Maybe some error when compiling shader, because variable name texture mathes with function name texture()? Try rename. – user1837009 Sep 05 '13 at 14:45
  • @fen: That's how sampler objects are unbound in OpenGL 3.3+. I don't think there's anything wrong with that, because the arcsynthesis tutorials teach modern OpenGL (including sampler objects for changing texture state) – Andon M. Coleman Sep 05 '13 at 16:35
  • @fen: Well according to what Andon said, it shouldn't make a difference... and it really didn't. – Jan Nowak Sep 06 '13 at 10:14
  • @user1837009: Tried that, renamed it texture2 and still made no difference – Jan Nowak Sep 06 '13 at 10:14
  • @AndonM.Coleman: Well thank you for that, it indeed made no difference, but what would your solution be? – Jan Nowak Sep 06 '13 at 10:15
  • @JanNowak: I strongly suspect that your `uniform sampler2D colorTexture` is to blame. You should be setting its value to `g_colorTexUnit` in your code, but I do not see where this is done. Since `g_colorTexUnit` is a constant, in newer versions of GLSL you can set the sampler's default location using the `location` layout qualifier. But I have not seen either your definition of this sampler in the GLSL shader or where you set it in your C++ code. – Andon M. Coleman Sep 06 '13 at 10:20
  • @AndonM.Coleman I forgot to mention: In "ProgramData LoadProgram", I've got these lines: GLuint colorTextureUnif = glGetUniformLocation(data.theProgram, "colorTexture"); glUseProgram(data.theProgram); glUniform1i(colorTextureUnif, g_colorTexUnit); glUseProgram(0); I just think this might be what you mean. Maybe – Jan Nowak Sep 07 '13 at 09:49
  • I'm not sure if that applies to OpenGL 3, but by default, textures have GL_LINEAR_MIPMAP_LINEAR min filter, which means textures REQUIRE mipmaps and are incomplete, unless you generate mipmaps (using glGenerateMipmaps or something else). Textures that are incomplete are rendered white in fixedfunction and black in shaders. To get rid of mipmaps, use GL_LINEAR for min filter. Another thing is that you should investigate warnings produced during shader compilation. They might give you a hint or two. – SigTerm Sep 10 '13 at 11:41

2 Answers2

1

Your fail to add textures may be caused by:

  • Have you add texture coordinates to objects? (this is the most probable cause, because you are adding textures to non textured tutorial), add textures to VAO.
  • Did you add uniform textureunit (Sampler2D)? (it must be uniform, else texturing will not work properly)
  • Is your texture loaded,binded,enabled (GL_TEXTURE_2D) ?
  • Is your active texture unit - 0? if not change layout/multitexture coords or set active texture 0

This two codes are simple texturing shaders (texture unit 0) no special things (like light,blend,bump,...):


tm_l2g is transformation local obj space -> world space (Modelview)
tm_g2s is transformation world space -> screen space (Projection)
pos are vertex coordinates
txt are texture coordinates
col are colors

Do not forget to change uniform names and layout locations to yours.

Vertex:

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
uniform mat4x4 tm_l2g;
uniform mat4x4 tm_g2s;

layout(location=0) in vec3 pos;
layout(location=1) in vec4 col;
layout(location=2) in vec2 txr;

out smooth vec4 pixel_col;
out smooth vec2 pixel_txr;
//------------------------------------------------------------------
void main(void)
    {
    vec4 p;
    p.xyz=pos;
    p.w=1.0;
    p=tm_l2g*p;
    p=tm_g2s*p;
    gl_Position=p;
    pixel_col=col;
    pixel_txr=txr;
    }
//------------------------------------------------------------------

fragment:

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
in smooth vec4 pixel_col;
in smooth vec2 pixel_txr;
uniform sampler2D   txr_texture0;
out layout(location=0) vec4 frag_col;
//------------------------------------------------------------------
void main(void)
    {
    vec4 col;
    col=texture(txr_texture0,pixel_txr.st);
    frag_col=col*pixel_col;
    }
//------------------------------------------------------------------

[edit1] CPU old style OpenGL render code (initializations are not included its only render code they can be found here)

//------------------------------------------------------------------
// set modelview,projection,textures,bind GLSL programs...
GLfloat a=10.0,z=0.0;
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
// textured quad
glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z);
glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z);
glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z);
glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z);
// reverse order quad to be shore that at least one passes by CULL_FACE
glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z);
glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z);
glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z);
glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z);
glEnd();

//------------------------------------------------------------------

[edit2] ok here goes VAO/VBO render code,...

//------------------------------------------------------------------------------
// enum of VBO locations (it is also your layout location) I use enums for simple in code changes
enum _vbo_enum
    {
    _vbo_pos=0,     // glVertex
    _vbo_col,       // glColor
    _vbo_tan,       // glNormal
    _vbo_unused0,   // unused (at least i dont see anything at this location in your code)
    _vbo_unused1,   // unused (at least i dont see anything at this location in your code)
    _vbo_txr,       // glTexCoord
    _vbos
    };
//------------------------------------------------------------------------------
// 'global' names and size for OpenGL mesh in VAO/VBO ... similar ot texture names/handles
GLuint vao[1],vbo[_vbos],num_pnt=0;
//------------------------------------------------------------------------------
void VAO_init_cube()    // call this before VAO use,...but after OpenGL init !
    {
    //[1] first you need some model to render (mesh), here is a simple cube
    // size,position of cube - change it that it is visible in your scene
    const GLfloat a=1.0,x=0.0,y=0.0,z=0.0;
    // cube points 3f x,y,z
    GLfloat mesh_pos[]=
        {
        x-a,y-a,z-a,x-a,y+a,z-a,x+a,y+a,z-a,x+a,y-a,z-a,
        x-a,y-a,z+a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y-a,z+a,
        x-a,y-a,z-a,x-a,y-a,z+a,x+a,y-a,z+a,x+a,y-a,z-a,
        x-a,y+a,z-a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y+a,z-a,
        x-a,y-a,z-a,x-a,y+a,z-a,x-a,y+a,z+a,x-a,y-a,z+a,
        x+a,y-a,z-a,x+a,y+a,z-a,x+a,y+a,z+a,x+a,y-a,z+a,
        };
    // cube colors 3f r,g,b
    GLfloat mesh_col[]=
        {
        0.0,0.0,0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0,0.0,0.0,
        0.0,0.0,1.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,1.0,
        0.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0,0.0,
        0.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,0.0,1.0,0.0,0.0,1.0,1.0,0.0,0.0,1.0,
        1.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,1.0,1.0,0.0,1.0,
        };
    // cube normals 3f x,y,z
    GLfloat mesh_tan[]=
        {
        -0.6,-0.6,-0.6,-0.6,+0.6,-0.6,+0.6,+0.6,-0.6,+0.6,-0.6,-0.6,
        -0.6,-0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6,
        -0.6,-0.6,-0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,-0.6,-0.6,
        -0.6,+0.6,-0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6,
        -0.6,-0.6,-0.6,-0.6,+0.6,-0.6,-0.6,+0.6,+0.6,-0.6,-0.6,+0.6,
        +0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6,
        };
    // cube texture coords 2f s,t
    GLfloat mesh_txr[]=
        {
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
        };
    // init VAO/VBO
    glGenVertexArrays(1,vao);   // allocate 1 x VAO
    glGenBuffers(_vbos,vbo);    // allocate _vbos x VBO
    // copy mesh to VAO/VBO ... after this you do not need the mesh anymore
    GLint i,sz,n;               // n = number of numbers per 1 entry
    glBindVertexArray(vao[0]);
    num_pnt=sizeof(mesh_pos)/(sizeof(GLfloat)*3);   // num of all points in mesh

    i=_OpenGLVAOgfx_pos; n=3; sz=sizeof(GLfloat)*n;
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_pos,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);

    i=_OpenGLVAOgfx_col; n=3; sz=sizeof(GLfloat)*n;
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_col,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);

    i=_OpenGLVAOgfx_tan; n=3; sz=sizeof(GLfloat)*n;
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_tan,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);

    i=_OpenGLVAOgfx_txr; n=2; sz=sizeof(GLfloat)*n;
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_txr,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);

    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
void VAO_draw() // call this to draw your mesh,... need to enable and bind textures,...  before use
    {
    glDisable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    glBindVertexArray(vao[0]);
     glEnableVertexAttribArray(_vbo_pos);
     glEnableVertexAttribArray(_vbo_col);
     glEnableVertexAttribArray(_vbo_tan);
    glDisableVertexAttribArray(_vbo_unused0);
     glEnableVertexAttribArray(_vbo_txr);

    glDrawArrays(GL_QUADS,0,num_pnt);

    glDisableVertexAttribArray(_vbo_pos);
    glDisableVertexAttribArray(_vbo_col);
    glDisableVertexAttribArray(_vbo_tan);
    glDisableVertexAttribArray(_vbo_unused0);
    glDisableVertexAttribArray(_vbo_unused1);
    glDisableVertexAttribArray(_vbo_txr);
    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
void VAO_exit() // clean up ... call this when you do not need VAO/VBO anymore
    {
    glDisableVertexAttribArray(_vbo_pos);
    glDisableVertexAttribArray(_vbo_col);
    glDisableVertexAttribArray(_vbo_tan);
    glDisableVertexAttribArray(_vbo_unused0);
    glDisableVertexAttribArray(_vbo_unused1);
    glDisableVertexAttribArray(_vbo_txr);
    glBindVertexArray(0);
    glDeleteVertexArrays(1,vao);
    glDeleteBuffers(_vbos,vbo);
    }
//------------------------------------------------------------------------------

[edit3] if you are win32/64 user you can try my IDE for GLSL

It is very simple and easy to use, but cannot change texture/attrib locations. Press [F1] for help,... [F9] for run [F10] for return to normal OpenGL mode. Also txt-editor is little buggy sometimes but it is enough for my purpose.

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • I appreciate the help here, but this doesn't seem to change much. To give more input I've expanded on the shaders. Don't know, if this makes helping me any easier. – Jan Nowak Sep 08 '13 at 13:30
  • yours shaders looks ok now, but in CPU code you need to add texcoords to your meshes. (they are from non textured tutorial so there is high probability that there are no texture coordinates) to check that call glTexCoord2f(0.1,0.1); before mesh render and see if color changes. if yes that means that your mash has no texture coords and need to add them (in CPU code not in shaders!) – Spektre Sep 08 '13 at 16:11
  • also you can try different texture coords not just 0.1,0.1 just to be shore (i don know how your texture looks like the idea is to hit different color than you have now) – Spektre Sep 08 '13 at 16:14
  • I'm afraid I can't apply "glTexCoord2f(0.1,0.1);" as it claims "glTexCoord2f" is undefined. Then again I doubt I should apply this at all given how the tutorials never use it.... Then again I don't know what else to try. – Jan Nowak Sep 09 '13 at 07:58
  • that is weird, glTexCoord is standart OpenGL 1.0 function so it must be there,... modern GLSL use VAO instead ... you need to create another VBO filled with your textcoords and bind it to your VAO instead of use of glTexCoord, but for testing should be enough what i wrote before – Spektre Sep 09 '13 at 18:23
  • Oh my... I know this sounds embarrassing, but I haven't really done this kind of stuff for months, I forgot how it works. – Jan Nowak Sep 10 '13 at 07:57
  • it is not embarrassing at all,... to simplify things for me i created wrapper class for my apps where OpenGL+GLSL+geometry computations are encapsulated so i do not need to remember low level stuff, just call init/load/save/cls/rfs/draw/exit and that is all... i will edit my answer in a moment ... to add CPU render code for testing – Spektre Sep 10 '13 at 09:09
  • ok old-style render is there insert it to your render routine,... but change a,z values so you see something, quad should be in front of your camera not behind and, a is size (if its too small you see nothing). VAO/VBO render is far more complicated will try to make something simpler and standalone from my wrapper class ... but it will take some time – Spektre Sep 10 '13 at 09:34
  • I added VAO/VBO render code,... i tested it, but check if i have the same layout locations ... if not change the order of enum. – Spektre Sep 10 '13 at 12:51
1

Ok guys, I've worked on this whole thing, and did manage to somehow get it running. First off I had to add samplers:

GLuint g_samplers;

//Add Later
void CreateSamplers()
{
glGenSamplers(1, &g_samplers);

    glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_T, GL_REPEAT);

//Linear mipmap Nearest
glSamplerParameteri(g_samplers, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(g_samplers, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}

I also added this to the file thing:

glimg::OpenGLPixelTransferParams xfer = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0);

glimg::SingleImage image = pImageSet->GetImage(0, 0, 0);
glimg::Dimensions dims = image.GetDimensions();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims.width, dims.height, 0, 
  xfer.format, xfer.type, image.GetImageData());

The xfer variable does get the format and type adjusted to the dds. Also the render code got turned into this:

//Added necessary 
glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
glBindTexture(GL_TEXTURE_2D,g_checkerTexture);
glBindSampler(g_colorTexUnit, g_samplers);
g_pLeftMesh->Render();
glBindSampler(g_colorTexUnit, 0);
glBindTexture(GL_TEXTURE_2D, 0);

And of course at the end of init() I needed to add the CreateSamplers thing:

//Added this later
LoadCheckerTexture();
CreateSamplers();

I'm sorry for all the trouble with all this, but guess OpenGL really is just this confusing and it was just dumb luck that I got it right. Just posting this so that people know

Jan Nowak
  • 45
  • 1
  • 7