Thursday, September 20, 2018

c++ - Why is my texture not applied correctly in OpenGL 2.0 with GLSL?


First off, this is a Uni assignment, but the lecturer is stumped too.



With the shader active, I get nothing, just black. With the shader disabled (fixed function pipeline) I get a rainbow pattern which is not the texture. Uncommenting the code block labeled with the comment //this does the texturing correctly but can't be used by the shader does as the comment states. My friends and I believe that I'm not loading the texture into OpenGL correctly, what am I doing wrong?


Here is the fragment shader:


const float     lightWeighting = 0.75;
const float textureWeighting = 0.25;


const float PI = 3.14;
const float lightIntensity = 1.0;
const float constFudge = 0.025;
const float linearFudge = 0.025;

const float quadraticFudge = 0.05;

float rend = 250.0;
float rstart = 50.0;


uniform float Intensity;
uniform sampler2D grabTexture;
//varying sampler2D HeatValues


varying vec3 Normal;
varying vec3 Vertex;
varying vec2 texCoord;

void main(void)
{
vec3 pigPos = Vertex;
vec3 normPigPos = normalize(pigPos);



vec3 lightPos = vec3(gl_LightSource[0].position.xyz);

vec3 normLightPos = normalize(lightPos);




float effectiveIntesity;



vec3 normNormal = normalize(vec3(Normal.xyz));

vec3 t = vec3(pigPos - lightPos);

float distToLight = length(t);

float d = dot(normNormal.xyz, normLightPos.xyz);
if(d > 0.0)//facing the light
{
float falloff;


if( distToLight < rstart )
falloff = 1.0;
else
if( distToLight > rend )
falloff = 0.0;
else
{
falloff = rend-distToLight / rend-rstart;
}


effectiveIntesity = d*lightIntensity * falloff;




effectiveIntesity = d*lightIntensity * (1.0/(constFudge + (linearFudge*distToLight) +(quadraticFudge*distToLight*distToLight)));

}
else

{
effectiveIntesity = 0.0;
}

//TODO: change the colour of the pixel
vec4 lightingColour = vec4(vec4( 1.0 ) * effectiveIntesity); //TODO: improve

//gl_FragColor = lightingColour;

//texturing stuff

//http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
vec4 textureColour = vec4(texture2D(grabTexture, texCoord.xy)); // TODO: why is this blank?

vec4 col = vec4(textureColour.rgb, 1.0);
col.r *= 1.0;
col.g *= 1.0;

gl_FragColor = (col);

//gl_FragColor = (lightingColour * lightWeighting) + (textureColour.rgb * textureWeighting);


//simple check to make sure that shader compiles
vec3 lP = vec3(abs(gl_LightSource[0].position.x/100), abs(gl_LightSource[0].position.y/100), abs(gl_LightSource[0].position.z/100));
vec4 r = vec4( lP.x, lP.y, lP.z, 1.0 );
gl_FragColor = r;

gl_FragColor = (lightingColour * lightWeighting) + (r * textureWeighting);
}

Here is what I do to load textures:



GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
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, x, y, 0, GL_RGB, GL_UNSIGNED_BYTE, rawLoadedTexture);

glBindTexture(GL_TEXTURE_2D, tex);

Using the texture:


glEnable(GL_TEXTURE_2D);

//this does the texturing correctly but can't be used by the shader
/*glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, rawLoadedTexture);*/

glActiveTexture(pigObj.id_texture); //the shader can use this texture
glBindTexture(GL_TEXTURE_2D, pigObj.id_texture);

cShader *pList = graphics.ShaderInfo.getList();
glUseProgram( pList[1].program()); //shader on: no pig // fixed, was vertex shader being empty, replaced it with intensity.vert
//shader off: ambient light only (tiny amount of diffuse or an illusion?)
extern NA_MathsLib na_maths;
float intensity = (float) na_maths.dice(100);


glUniform1i(pList[1].get_grabLoc(), pigObj.id_texture);
glUniform1f(pList[1].intensity(), intensity);
//glUniform1f(pList[1].get_heatValues(), heatValuesPsudoTexture);

//glutSolidSphere(2, 15, 2);
pigObj.render();

glDisable(GL_TEXTURE_2D);
glUseProgram(0); //disable pig heatlamp shader


Answer



Your problem is here:


glActiveTexture(pigObj.id_texture); //the shader can use this texture

glActiveTexture() takes a value of GL_TEXTURE*, not the ID of your texture. It's the texture unit in which your texture is going to be bound (or is already bound). So for texture unit 0, you'd do:


glActiveTexture(GL_TEXTURE0);

You then need to also pass the texture unit index as the uniform for the sampler, rather than your texture ID.


This is by far one of the most confusing aspects of texturing in OpenGL! And because all OpenGL constants are #defines instead of proper named types, it's really hard to have the compiler catch this type of error. See the docs for glActiveTexture() for more info.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...