Related
I am rendering video using opengl in qml using QQuickFramebufferObject but output what ever i am seeing is mirror of original.
what might be the wrong.
code:
QOpenGLShaderProgram *m_Program;
glGenTextures(3, m_Texture);
m_Program = new QOpenGLShaderProgram();
m_Program->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 a_position;"
"attribute vec2 a_texcoord;"
"varying vec2 v_texcoord;"
"void main()"
"{"
" gl_Position = a_position;"
" v_texcoord = a_texcoord;"
"}"
);
m_Program->addShaderFromSourceCode(QOpenGLShader::Fragment,
"varying vec2 v_texcoord;"
"uniform sampler2D u_Texture0;"
"uniform sampler2D u_Texture1;"
"uniform sampler2D u_Texture2;"
"uniform mat4 u_colorMatrix;"
"void main()"
"{"
" gl_FragColor = u_colorMatrix * vec4("
" texture2D(u_Texture0, v_texcoord).s,"
" texture2D(u_Texture1, v_texcoord).t,"
" texture2D(u_Texture2, v_texcoord).q,"
" 1.0);"
"}"
);
m_Program->bindAttributeLocation("a_position", 0);
m_Program->bindAttributeLocation("a_texcoord", 1);
m_Program->link();
static double prevPos = 0.0;
glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
if(m_PlaneWidth == -1)
{
_clearView();
return;
}
m_Program->bind();
m_Program->enableAttributeArray(0);
m_Program->enableAttributeArray(1);
setPlayerPosition();
m_pw=m_ph=1.0;
float position[] =
{
m_pw, m_ph,
m_pw, -m_ph,
-m_pw, -m_ph,
-m_pw, m_ph
};
float w =1.0-(m_PlaneWidth-float(m_ptrMediator->getWidth()))/m_PlaneWidth;
float coord[] =
{
0.0, 1.0,
0.0, 0.0,
w, 0.0,
w, 1.0
};
m_Program->setAttributeArray(0, GL_FLOAT, position, 2);
m_Program->setAttributeArray(1, GL_FLOAT, coord, 2);
const qreal zNear = 1.0, zFar = 4.0, fov = 45.0;
const qreal aspect = m_ptrMediator->getWidth()/m_ptrMediator->getHeight();
m_Projection.setToIdentity();
m_Projection.perspective(fov, aspect, zNear, zFar);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
refresh(&pFrame);
m_Program->disableAttributeArray(0);
m_Program->release();
glActiveTextureARB(GL_TEXTURE2_ARB);
glBindTexture(GL_TEXTURE_2D, m_Texture[2]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pFrame->width,
pFrame->height, GL_LUMINANCE,
GL_UNSIGNED_BYTE, pFrame->data[0]);
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, m_Texture[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pFrame->width/2,
pFrame->height/2, GL_LUMINANCE,
GL_UNSIGNED_BYTE, pFrame->data[1]);
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pFrame->width/2,
pFrame->height/2, GL_ALPHA,
GL_UNSIGNED_BYTE, pFrame->data[2]);
m_Program->setUniformValue("u_Texture0", 2/*m_Texture[2]-1*/);
m_Program->setUniformValue("u_Texture1", 1/*m_Texture[1]-1*/);
m_Program->setUniformValue("u_Texture2", 0/*m_Texture[0]-1*/);
m_Program->setUniformValue("u_colorMatrix", m_Conv);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
if i change position i can able to see some changes but still i am not getting actual data.
Could some one help me out of this
I just modified position and texture coordinates it starting working.
m_pw=m_ph=1.0;
float position[] =
{
-m_pw, -m_ph,
m_pw, -m_ph,
m_pw, m_ph,
-m_pw, m_ph
};
float w =1.0-(m_PlaneWidth-float(m_ptrMediator->getWidth()))/m_PlaneWidth;
float coord[] =
{
0.0, 0.0,
w, 0.0,
w, 1.0,
0.0, 1.0
};
I am trying to detect silhouette edges and render some textures (varies based on the diffuse term) on these edges using OpenGL and shaders. I am rendering a quad using the geometry shader and also assign the texture coordinates here. In the fragment shader, i am trying to use the diffuse term calculated in vertex shader to render different textures based on diffTerm's value. There are two issues with my code.
1) The diffuse term should vary from (-1,1) but it seems to be stuck at 0 when i rotate the model and it reaches negative values at certain positions.
2) The textures are always black and I cant seem to find out what is causing this issue.
"MeshViewer.cpp" - The main file
Mesh* mesh;
GLuint* texID = new GLuint[5];
float rotn_x = 0.0, rotn_y = 0.0, fov;
GLuint matrixLoc1, matrixLoc2, matrixLoc3,texLoc1, texLoc2, texLoc3, texLoc4, texLoc5;
float cam_near, cam_far; //Near and far planes of the camera
const float PI = 3.14159265f;
glm::mat4 view; //View and projection matrices
void loadTextures()
{
glGenTextures(5, texID); //Generate 1 texture ID
glActiveTexture(GL_TEXTURE0); //Texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[0]);
loadTGA("Pencil0.tga");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE1); //Texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[1]);
loadTGA("Pencil1.tga");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE2); //Texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[2]);
loadTGA("Pencil2.tga");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE3); //Texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[3]);
loadTGA("Brick.tga");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE4); //Texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[4]);
loadTGA("Brick.tga");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void initialise()
{
// --- Mesh object ---
GLuint lgtLoc;
mesh = new Mesh();
if(!mesh->loadMeshOFF("Camel.off")) cout << "Error reading mesh data file." << endl;
// --- Camera parameters ---
float win_width = (mesh->_xmax - mesh->_xmin) * 1.5f;
float win_height = (mesh->_ymax - mesh->_ymin) * 1.5f;
if(win_width > win_height) win_height = win_width; //Maintain aspect ratio = 1
cam_near = 2*(mesh->_zmax) - mesh->_zmin;
cam_far = 2*(mesh->_zmin) - mesh->_zmax;
float cam_posx = (mesh->_xmax + mesh->_xmin) * 0.5f;
float cam_posy = (mesh->_ymax + mesh->_ymin) * 0.5f;
float cam_posz = cam_near + win_height;
fov = 27.0f; //Approx. atan(0.5)
// --- Uniform locations ---
GLuint program = createShaderProg("MeshViewer.vert", "MeshViewer.frag", "MeshViewer.geom");
matrixLoc1 = glGetUniformLocation(program, "mvMatrix");
matrixLoc2 = glGetUniformLocation(program, "mvpMatrix");
matrixLoc3 = glGetUniformLocation(program, "norMatrix");
lgtLoc = glGetUniformLocation(program, "lightPos");
GLint lineWidth = glGetUniformLocation(program, "HalfWidth");
if (lineWidth > -1)
glUniform1f(lineWidth, 0.005f);
GLint overhangLength = glGetUniformLocation(program, "OverhangLength");
if (overhangLength > -1)
glUniform1f(overhangLength, 0.15f);
texLoc1 = glGetUniformLocation (program, "tex1");
glUniform1i(texLoc1, 0);
texLoc2 = glGetUniformLocation (program, "tex2");
glUniform1i(texLoc2, 1);
texLoc3 = glGetUniformLocation (program, "tex3");
glUniform1i(texLoc3, 2);
texLoc4 = glGetUniformLocation (program, "tex4");
glUniform1i(texLoc4, 3);
texLoc5 = glGetUniformLocation (program, "tex5");
glUniform1i(texLoc5, 4);
view = glm::lookAt(glm::vec3(cam_posx, cam_posy, cam_posz), glm::vec3(cam_posx, cam_posy, 0.0), glm::vec3(0.0, 1.0, 0.0)); //view matrix
glm::vec4 light = glm::vec4(100.0, 50.0, 100.0, 1.0); //Light's position
glm::vec4 lightEye = view*light; //Light position in eye coordinates
glUniform4fv(lgtLoc, 1, &lightEye[0]);
// --- OpenGL ---
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //Wireframe
mesh->setColor(0, 0, 1); //Mesh color = blue.
mesh->createVAO(); //Create buffer objects for the mesh
}
void display()
{
glm::mat4 proj;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 matrix = glm::mat4(1.0);
matrix = glm::rotate(matrix, rotn_x, glm::vec3(1.0, 0.0, 0.0)); //rotation about x
matrix = glm::rotate(matrix, rotn_y, glm::vec3(0.0, 1.0, 0.0)); //rotation about y
glm::mat4 prodMatrix1 = view*matrix; //Model-view matrix
proj = glm::perspective(fov, 1.0f, cam_near, cam_far); //perspective projection matrix
glm::mat4 prodMatrix2 = proj*prodMatrix1; //The model-view-projection transformation
glm::mat4 invMatrix = glm::inverse(prodMatrix1); //Inverse of model-view matrix for normal transformation
glUniformMatrix4fv(matrixLoc1, 1, GL_FALSE, &prodMatrix1[0][0]);
glUniformMatrix4fv(matrixLoc2, 1, GL_FALSE, &prodMatrix2[0][0]);
glUniformMatrix4fv(matrixLoc3, 1, GL_TRUE, &invMatrix[0][0]); //Use transpose matrix here
mesh->render();
glFlush();
}
void specialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_LEFT) rotn_y -= 5.0;
else if(key == GLUT_KEY_RIGHT) rotn_y += 5.0;
else if(key == GLUT_KEY_UP) rotn_x -= 5.0;
else if(key == GLUT_KEY_DOWN) rotn_x += 5.0;
else if(key == GLUT_KEY_PAGE_UP) fov --;
else if(key == GLUT_KEY_PAGE_DOWN) fov ++;
if(fov < 1.0) fov = 1.0;
else if(fov > 80.0) fov = 80.0;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (600, 600);
glutInitWindowPosition (20, 10);
glutCreateWindow ("Mesh Viewer");
glutInitContextVersion (4, 2);
glutInitContextProfile ( GLUT_CORE_PROFILE );
if(glewInit() == GLEW_OK)
{
cout << "GLEW initialization successful! " << endl;
cout << " Using GLEW version " << glewGetString(GLEW_VERSION) << endl;
}
else
{
cerr << "Unable to initialize GLEW ...exiting." << endl;
exit(EXIT_FAILURE);
}
initialise ();
glutDisplayFunc(display);
glutSpecialFunc(specialKeys);
glutMainLoop();
return 0;
}
Vertex Shader:
#version 330
layout (location = 0) in vec4 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 cols;
layout (location = 3) in vec2 texC;
uniform mat4 mvMatrix;
uniform mat4 mvpMatrix;
uniform mat4 norMatrix;
uniform vec4 lightPos;
out float diffTerm;
out vec4 vColour;
out float viewTerm;
out float silhoutte;
out vec2 TexC;
void main()
{
vec4 grey = vec4(0.2, 0.2, 0.2, 1.0);
vec4 posnEye = mvMatrix * position;
vec4 normalEye = norMatrix * vec4(normal, 0);
vec4 lgtVec = normalize(lightPos - posnEye);
vec4 viewVec = normalize(vec4(-posnEye.xyz, 0));
float viewTerm = max(dot(viewVec, normalEye),0);
vec4 material = vec4(cols, 1.0);
vec4 lgtAmb = grey * material;
diffTerm = max(dot(lgtVec, normalEye), 0);
vec4 lgtDiff = material * diffTerm;
silhoutte = dot(viewVec, normalEye);
gl_Position = mvpMatrix * position;
vColour = vec4(cols, 1);
TexC = texC;
}
Geometry Shader:
#version 430 core
layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices = 6) out;
in vec2 texC[];
out vec2 TexCoord;
in vec4 vColour[];
out vec4 colorv;
in float viewTerm[];
out float viewTermg;
in float diffTerm[];
out float diffTermg;
in vec2 TexC[];
out vec2 TexCg;
uniform float HalfWidth;
uniform float OverhangLength;
out float gDist;
out vec3 gSpine;
bool IsFront(vec3 A, vec3 B, vec3 C)
{
float area = (A.x * B.y - B.x * A.y) + (B.x * C.y - C.x * B.y) + (C.x * A.y - A.x * C.y);
return area > 0;
}
void EmitEdge(vec3 P0, vec3 P1)
{
vec3 E = OverhangLength * vec3(P1.xy - P0.xy, 0);
vec2 V = normalize(E.xy);
vec3 N = vec3(-V.y, V.x, 0) * 0.005;
vec3 S = -N;
float D = HalfWidth;
gSpine = P0;
gl_Position = vec4(P0 + S - E, 1); gDist = +D; TexCoord=vec2(0.0,0.0); colorv = vColour[0]; EmitVertex();
gl_Position = vec4(P0 + N - E, 1); gDist = -D; TexCoord=vec2(1.0,0.0); colorv = vColour[1]; EmitVertex();
gSpine = P1;
gl_Position = vec4(P1 + S + E, 1); gDist = +D; TexCoord=vec2(1.0,1.0); colorv = vColour[0]; EmitVertex();
gl_Position = vec4(P1 + N + E, 1); gDist = -D; ; TexCoord=vec2(0.0,1.0); EmitVertex();
EndPrimitive();
}
void main()
{
vec3 v0 = gl_in[0].gl_Position.xyz / gl_in[0].gl_Position.w;
vec3 v1 = gl_in[1].gl_Position.xyz / gl_in[1].gl_Position.w;
vec3 v2 = gl_in[2].gl_Position.xyz / gl_in[2].gl_Position.w;
vec3 v3 = gl_in[3].gl_Position.xyz / gl_in[3].gl_Position.w;
vec3 v4 = gl_in[4].gl_Position.xyz / gl_in[4].gl_Position.w;
vec3 v5 = gl_in[5].gl_Position.xyz / gl_in[5].gl_Position.w;
if (IsFront(v0, v2, v4)) {
if (!IsFront(v0, v1, v2)) EmitEdge(v0, v2);
//if (!IsFront(v2, v3, v4)) EmitEdge(v2, v4);
//if (!IsFront(v0, v4, v5)) EmitEdge(v4, v0);
}
}
Fragment Shader:
#version 330
in vec4 vColourg;
in float diffTermg;
in float silhoutte;
in vec2 TexCg;
in vec2 TexCoord;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2D tex4;
uniform sampler2D tex5;
void main()
{
vec4 texColor1 = texture(tex1, TexCoord);
vec4 texColor2 = texture(tex2, TexCoord);
vec4 texColor3 = texture(tex3, TexCoord);
vec4 texColor4 = texture(tex4, TexCoord);
vec4 texColor5 = texture(tex5, TexCoord);
vec4 blue = vec4(0.0,0.0,1.0,0.0);
vec4 red = vec4(1.0,0.0,0.0,0.0);
vec4 yellow = vec4(1.0,1.0,0.0,0.0);
if (diffTermg<0)
{
gl_FragColor = blue;
}
else if (diffTermg ==0)
{
gl_FragColor = texColor5;
}
else if (diffTermg > 0 && diffTermg < 0.2)
gl_FragColor = yellow;
else if (diffTermg > 100)
gl_FragColor = blue;
}
EDIT:
Shader.h
GLuint loadShader(GLenum shaderType, string filename)
{
ifstream shaderFile(filename.c_str());
if(!shaderFile.good()) cout << "Error opening shader file." << endl;
stringstream shaderData;
shaderData << shaderFile.rdbuf();
shaderFile.close();
string shaderStr = shaderData.str();
const char* shaderTxt = shaderStr.c_str();
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &shaderTxt, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
const char *strShaderType = NULL;
cerr << "Compile failure in shader: " << strInfoLog << endl;
delete[] strInfoLog;
}
return shader;
}
GLuint createShaderProg(string vertShader, string fragShader, string geomShader)
{
GLuint shaderv = loadShader(GL_VERTEX_SHADER, vertShader);
GLuint shaderf = loadShader(GL_FRAGMENT_SHADER, fragShader);
GLuint shaderg = loadShader(GL_GEOMETRY_SHADER, geomShader);
GLuint program = glCreateProgram();
glAttachShader(program, shaderv);
glAttachShader(program, shaderf);
glAttachShader(program, shaderg);
glLinkProgram(program);
GLint status;
glGetProgramiv (program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
delete[] strInfoLog;
program = 0;
}
glUseProgram(program);
return program;
}
loadTGA.h
void loadTGA(string filename)
{
char id, cmap, imgtype, bpp, c_garb;
char* imageData, temp;
short int s_garb, wid, hgt;
int nbytes, size, indx;
ifstream file( filename.c_str(), ios::in | ios::binary);
if(!file)
{
cout << "*** Error opening image file: " << filename.c_str() << endl;
exit(1);
}
file.read (&id, 1);
file.read (&cmap, 1);
file.read (&imgtype, 1);
if(imgtype != 2 && imgtype != 3 ) //2= colour (uncompressed), 3 = greyscale (uncompressed)
{
cout << "*** Incompatible image type: " << (int)imgtype << endl;
exit(1);
}
//Color map specification
file.read ((char*)&s_garb, 2);
file.read ((char*)&s_garb, 2);
file.read (&c_garb, 1);
//Image specification
file.read ((char*)&s_garb, 2); //x origin
file.read ((char*)&s_garb, 2); //y origin
file.read ((char*)&wid, 2); //image width
file.read ((char*)&hgt, 2); //image height
file.read (&bpp, 1); //bits per pixel
file.read (&c_garb, 1); //img descriptor
nbytes = bpp / 8; //No. of bytes per pixels
size = wid * hgt * nbytes; //Total number of bytes to be read
imageData = new char[size];
file.read(imageData, size);
//cout << ">>>" << nbytes << " " << wid << " " << hgt << endl;
if(nbytes > 2) //swap R and B
{
for(int i = 0; i < wid*hgt; i++)
{
indx = i*nbytes;
temp = imageData[indx];
imageData[indx] = imageData[indx+2];
imageData[indx+2] = temp;
}
}
switch (nbytes)
{
case 1:
glTexImage2D(GL_TEXTURE_2D, 0, 1, wid, hgt, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData);
break;
case 3:
glTexImage2D(GL_TEXTURE_2D, 0, 3, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
break;
case 4:
glTexImage2D(GL_TEXTURE_2D, 0, 4, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
break;
}
delete imageData;
}
You are requesting a core profile context:
glutInitContextProfile(GLUT_CORE_PROFILE);
But your glTexImage2D() calls are not compatible with the core profile:
glTexImage2D(GL_TEXTURE_2D, 0, 1, wid, hgt, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData);
glTexImage2D(GL_TEXTURE_2D, 0, 3, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexImage2D(GL_TEXTURE_2D, 0, 4, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
Using the number of components as the internal format (argument 3) is legacy from OpenGL 1.0, and was finally eliminated when the core profile was introduced. GL_LUMINANCE is also gone. The modern (core profile) equivalent of those calls is:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, wid, hgt, 0, GL_RED, GL_UNSIGNED_BYTE, imageData);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
The post contains a lot of code, and I did not study it in detail to see if there are other problems. I strongly recommend the use of glGetError(), which would have reported these invalid arguments, and should also be helpful to check if there are any additional problems.
I am using freetype to display text, with the the help of this tutorial: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01
But all i see is empty squares, I played around a lot with the shaders and came to a conclusion that that the alpha value of the squares was always 0.0 also for some reason the program crashes after first time of compiling edited text shaders
This is the code:
Vertex Shader
#version 420
//vertexData.xy contains pos vertexData.zw contains uv coords
in vec4 vertexData;
out vec2 TexCoord;
void main(){
gl_Position = vec4(vertexData.x, vertexData.y, 0.0, 1.0);
TexCoord = vertexData.zw;
}
Fragment Shader
#version 420
in vec2 TexCoord;
out vec4 fragData;
uniform sampler2D tex;
uniform vec4 TextColor;
void main(){
//TextColor.rgb is the color texture(tex, TexCoord).r is texture alpha value
fragData = vec4(TextColor.rgb, texture(tex, TexCoord).r * TextColor.a);
}
FreeType
//Freetype init and face creation is in func Font::init()
void Font::renderText(const char *text, float x, float y, float sx, float sy, float rgba[4]){
//Attribute and Uniform Locations
GLint vDataLoc = ShaderResource::TextProgram->getAttributeLocation("vertexData");
GLint textColLoc = ShaderResource::TextProgram->getUniformLocation("TextColor");
GLint texSamplerLoc = ShaderResource::TextProgram->getUniformLocation("tex");
const char *p;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FT_Set_Pixel_Sizes(face, 0, 48);
//iterate through text
for(p = text; *p; p++) {
if(FT_Load_Char(face, *p, FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = face->glyph;
int width = to_nearest_pow2( g->bitmap.width );
int height = to_nearest_pow2( g->bitmap.rows );
glUniform4fv(textColLoc, 1, rgba);
glEnable(GL_TEXTURE_2D);
Texture Tex;
Tex = Texture();
Tex.bind();
Tex.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP);
Tex.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//At first I thought I was passing wrong formats to glteximage2d so I played around with it using gl alpha, gl luminance alpha, gl luminance8 alpha8 etc...
//I believe the issue is that g->bitmap.buffer was not created properly i must not be loading that char correctly??
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
width,
height,
0,
GL_RED,
GL_UNSIGNED_BYTE,
g->bitmap.buffer
);
Tex.active(0);
glUniform1i(texSamplerLoc, 0);
//Then I create textbox and draw it using a vertex array obj and vbos using gl triangle strip etc...
Main.cpp Freetype Func call
//Disable Normal Shader Enable Text Shader
mainProgram->disable();
textProgram->use();
//Scale x & Scale y / window get screen width and height
float sx = 2.0 / window->getFrameBufferWidth();
float sy = 2.0 / window->getFrameBufferHeight();
//Text color
float color[4] = {0.0,0.0,0.0,1.0};
IHateComicSans.renderText("Hello World!", 0.0, 0.0, sx, sy, color);
textProgram->disable();
mainProgram->use();
After gltexImage2d glGetError returns GL_INVALID_OPERATION but only during the last iteration of the text
The problem was in my Texture class, fixed by just using opengl functions.
As the title says, I've been having troubles with normal mapping. First, a bit of background...
I was following TheCPlusPlusGuy's tutorials, using LWJGL, and ran into errors. I put a post on here, but it got no replies. I then moved into C++, and, once again, got back into normal mapping, and found more issues. The problem is, that when I move in the X-axis, the light appears to move as though I'm moving in the Y-axis. I've rendered the normal map texture, as a regular texture, and it works normally, so the bug therefore should be in the shaders.
I made a video of the bug, on YouTube here.
Here's the code:
vertex.vert:
#version 120
precision highp float;
varying vec2 texCoord;
varying vec3 position;
varying vec3 normal;
uniform vec3 lightPos;
varying vec3 tangentSurface2light;
varying vec3 tangentSurface2view;
mat3 getTangentMatrix(){
vec3 tangent;
vec3 v1 = cross(gl_Normal, vec3(0.0, 1.0, 0.0));
vec3 v2 = cross(gl_Normal, vec3(0.0, 0.0, 1.0));
if(length(v1) > length(v2)){
tangent = v1;
}else{
tangent = v2;
}
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * tangent);
vec3 b = cross(n, t);
mat3 mat = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.x, n.z);
return transpose(mat);
}
void main(){
mat3 tangent = getTangentMatrix();
texCoord = gl_MultiTexCoord0.xy;
gl_Position = ftransform();
position = vec3(gl_ModelViewMatrix * gl_Vertex);
normal = gl_NormalMatrix * gl_Normal;
vec3 vector = normalize(lightPos - position);
tangentSurface2light = tangent * vector;
vector = normalize(-position);
tangentSurface2view = tangent * vector;
}
fragment.frag:
#version 120
precision highp float;
varying vec2 texCoord;
uniform sampler2D texture;
uniform sampler2D normalMap;
varying vec3 position;
varying vec3 normal;
varying vec3 tangentSurface2light;
varying vec3 tangentSurface2view;
uniform vec3 lightPos;
uniform vec3 mambient;
uniform vec3 mdiffuse;
uniform vec3 mspecular;
uniform float shininess;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
void main(){
float dist = length(position - lightPos);
float att = 1.0/(0.005*dist*dist);
vec3 tdiffuse = vec3(texture2D(texture, texCoord)) * mdiffuse;
vec3 ambient = mambient * lambient;
vec3 surf2light = normalize(tangentSurface2light);
vec3 norm = normalize(texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);
float dcont = max(0.0, dot(norm, surf2light));
vec3 diffuse = dcont * tdiffuse * ldiffuse;
vec3 surf2view = normalize(tangentSurface2view);
vec3 reflection = reflect(-surf2light, norm);
float scont = pow(max(0.0, dot(surf2view, reflection)), shininess);
scont = max(0.0, dot(surf2view, reflection));
vec3 specular = scont * mspecular * lspecular;
gl_FragColor=vec4((ambient + diffuse + specular )* att, 1.0);
}
And just in case, main.cpp (Note functions.h is just the first person camera):
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "GLee.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL_opengl.h>
#include <SDL/SDL_mouse.h>
#include <math.h>
#include <SDL/SDL_opengl.h>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include "functions.h"
//#include <SDL/SDL_video.h>
#define PI 3.14159265358979323846264338327
using namespace std;
unsigned int frame, texture, normalMap;
long double lPos = 0;
bool mousein = false;
#include "GLee.h"
void loadFile(const char* fn, string& str){
ifstream in(fn);
if(!in.is_open()){
cout<<"The file "<<fn<<"could not be opened!"<<endl;
return;
}
char tmp[300];
while(!in.eof()){
in.getline(tmp, 300);
str += tmp;
str += '\n';
}
}
unsigned int loadShader(string& source, unsigned int mode){
unsigned int id;
id = glCreateShader(mode);
const char* csource = source.c_str();
glShaderSource(id, 1, &csource, NULL);
glCompileShader(id);
char error[1000];
glGetShaderInfoLog(id, 1000, NULL, error);
cout<<"Compile Status: \n"<<error<<endl;
return id;
}
unsigned int vs, fs, program;
void initShader(const char* vname, const char* fname, unsigned int& program){//20:30 into vid...
string source;
loadFile(vname, source);
vs = loadShader(source, GL_VERTEX_SHADER);
source = "";
loadFile(fname, source);
fs = loadShader(source, GL_FRAGMENT_SHADER);
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glUseProgram(program);
}
void clean(const int& program){
glDetachShader(program, vs);
glDetachShader(program, fs);
glDeleteShader(vs);
glDeleteShader(fs);
glDeleteProgram(program);
}
void gluPerspective( GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar ){
const GLdouble pi = 3.1415926535897932384626433832795;
GLdouble fW, fH;
fH = tan( fovY / 360 * pi ) * zNear;
fW = fH * aspect;
glFrustum( -fW, fW, -fH, fH, zNear, zFar );
}
unsigned int loadTexture(const char* fileName){
//IMG_Init(0);
GLint numberOfColours = 0;
GLenum format;
SDL_Surface* img = IMG_Load(fileName);
img = SDL_DisplayFormatAlpha(img);
cout<<IMG_GetError();
//numberOfColours = img->format->BytesPerPixel;
if(!(&img)){
cout<<"Failed To Find Image!"<<endl;
}
cout<<"Reached load!"<<endl;
if(((img->w & (img->w - 1)) != 0)){cout<<"Warning: Image width not a power of 2!"<<endl;}
if(((img->h & (img->h - 1)) != 0)){cout<<"Warning: Image height not a power of 2!"<<endl;}
if(img->format->BytesPerPixel == 4){
format = GL_RGBA;
}else{
format = GL_RGB;
}
cout<<"GL_RGB: "<<GL_RGB<<"\nFormat: "<<format<<endl;
// SDL_PixelFormat pf;
//pf.palette = 0;
//pf.BitsPerPixel = 32;
//pf.BytesPerPixel = 4;
//pf.alpha = 255;
//pf.Rshift = pf.Rloss = pf.Gloss = pf.Bloss = pf.Aloss = pf.colorkey = 0;
//pf.Rmask = 0x000000ff;
//pf.Gshift = 8;
//pf.Gmask = 0x0000ff00;
//pf.Bshift = 16;
//pf.Bmask = 0x00ff0000;
//pf.Ashift = 24;
//pf.Amask = 0xff000000;
//SDL_Surface* glSurface = SDL_ConvertSurface(img, &pf, SDL_SWSURFACE);
unsigned int id;
glGenTextures(1, &id);
cout<<"ID: "<<id<<endl;
glBindTexture(GL_TEXTURE_2D, id);
cout<<"IMG Error: "<<IMG_GetError()<<endl;
cout<<"SDL Error: "<<SDL_GetError()<<endl;
glTexImage2D(GL_TEXTURE_2D, 0, format, img->w, img->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, img->pixels);
cout<<"IMG Error: "<<IMG_GetError()<<endl;
cout<<"SDL Error: "<<SDL_GetError()<<endl;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP,GL_TRUE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
SDL_FreeSurface(img);
return id;
}
SDL_Surface* loadTextureData(const char* fileName){
SDL_Surface* tex;
if((tex = IMG_Load(fileName))){
cout<<"Texture Found! Tex: "<<fileName<<endl;
}
return tex;
}
void init(){
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
const unsigned char* text = glGetString(GL_VERSION);
SDL_WM_GrabInput(SDL_GRAB_ON);
glEnable(GL_MULTISAMPLE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_WM_SetCaption("OGL!", "OGL!!");
//SDL_WM_IconifyWindow();
SDL_Surface* icon = loadTextureData("Logo.png");
SDL_WM_SetIcon(icon, NULL);
glClearColor(0.0, 0.0, 0.0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1280.0/720.0, 0.1, 5000.0);
glMatrixMode(GL_MODELVIEW);
SDL_FreeSurface(icon);
texture = loadTexture("Moon.png");
normalMap = loadTexture("Normal Map.png");
SDL_ShowCursor(false);
initShader("vertex.vert", "fragment.frag", program);
}
void display(){
//frame++;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUniform1i(glGetUniformLocation(program, "texture"), 0);
glUniform1i(glGetUniformLocation(program, "normalMap"), 1);
glUniform3f(glGetUniformLocation(program, "lightPos"), 0, 0, 0);
glUniform3f(glGetUniformLocation(program, "mambient"), 0.2, 0.2, 0.2);
glUniform3f(glGetUniformLocation(program, "mdiffuse"), 0.6, 0.6, 0.6);
glUniform3f(glGetUniformLocation(program, "mspecular"), 1, 1, 1);
glUniform1f(glGetUniformLocation(program, "shininess"), 0);
glUniform3f(glGetUniformLocation(program, "lambient"), 0.2, 0.2, 0.2);
glUniform3f(glGetUniformLocation(program, "ldiffuse"), 0.4, 0.4, 0.4);
glUniform3f(glGetUniformLocation(program, "lspecular"), 1, 1, 1);
glUniform3f(glGetUniformLocation(program, "lightPos"), /*lPos*/0, 0, 0);
glLoadIdentity();
control(0.2, 0.2, mousein);
updateCamera();
//glTranslatef(0.0, 0.0, -6);
//glRotatef(frame, 0, 1, 0);
//glRotatef(90, 0, 1, 0);
/*glBegin(GL_TRIANGLES);
glScalef(15, 15, 15);
glColor4f(1.0, 0.0, 0.0, 1);
glVertex3f(0.0, 2.0, 0.0);
glColor4f(0.0, 1.0, 0.0, 1);
glVertex3f(-2.0, -2.0, 0.0);
glColor4f(0.0, 0.0, 1.0, 1);
glVertex3f(2.0, -2.0, 0.0);
glEnd();*/
//glRotatef(90, 0, 1, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, normalMap);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normalMap);
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glColor4f(1.0,1.0,1.0, 1.0);
glTexCoord2i(0, 0);
glVertex3f(-2.0, 2.0, 0.0);
glTexCoord2i(1, 0);
glVertex3f(-2.0, -2.0, 0.0);
glTexCoord2i(1, 1);
glVertex3f(2.0, -2.0, 0.0);
glTexCoord2i(0, 1);
glVertex3f(2.0, 2.0, 0.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
void update(){
frame++;
lPos = sin((180/PI)*(frame/10))*5;
}
int main(int args, char* argv[]){
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_Surface* screen = SDL_SetVideoMode(1280, 720, 32, SDL_SWSURFACE|SDL_OPENGL);
bool running = true;
Uint32 start;
SDL_Event event;
init();
while(running){
start = SDL_GetTicks();
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym){
default:
break;
case SDLK_ESCAPE:
running = false;
break;
case SDLK_p:
mousein = false;
SDL_ShowCursor(SDL_ENABLE);
break;
}
break;
case SDL_KEYUP:
break;
case SDL_MOUSEBUTTONDOWN:
mousein = true;
SDL_ShowCursor(SDL_DISABLE);
break;
}
}
update();
display();
SDL_GL_SwapBuffers();
if(1000/60 > (SDL_GetTicks() - start)){
SDL_Delay(1000/60 - (SDL_GetTicks() - start));
}
}
clean(program);
SDL_Quit();
//cout << "Hello world!" << endl;
return 0;
}
My program has been working perfectly so far, but it turns out that I've been lucky. I began doing some cleanup of the shader, because it was full of experimental stuff, and I had the following line at the end of the fragment shader:
gl_FragColor = final_color * (texture2D(tex, gl_TexCoord[0].st)*1.0 + texture2D(tex2, gl_TexCoord[0].st)*1.0);
I attempted to clean it up and I had the following declared at the top:
uniform sampler2D tex, tex2;
Changing these lines to:
gl_FragColor = final_color * texture2D(tex, gl_TexCoord[0].st;
and
uniform sampler2D tex;
actually broke the program (black screen), even though I am doing
GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
glUniform1i(tex_loc, texture_id_);
in my main code. I'm sure it's a texture issue and not a glsl compiler error, because I can add 1.0 to the output and end up with a white silhouette of my mesh.
The strangeness begins when I change the lines in my shader to:
gl_FragColor = final_color * texture2D(tex2, gl_TexCoord[0].st;
and
uniform sampler2D tex2;
but still retrieve the location for tex. The program works as it always has, even though inspecting the value of tex_loc in the debugger indicates an error. I'm not happy doing this, and now that I'm trying to load multiple textures, it will cause bigger headaches down the line.
I'm using VBOs, in interleaved format, to render the geometry. I'm passing in the vertex position, normal and texcoord this way.
There are other questions with the "black texture" issue, but they're using immediate mode calls and setting the wrong texture state. I tried changing the texture unit before supplying the arrays, with no success.
Here is as much relevant code as possible from the main program:
void MeshWidget::draw() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_);
glRotatef(rotX, 1.0f, 0.0f, 0.0f);
glRotatef(rotY, 0.0f, 1.0f, 0.0f);
glRotatef(rotZ, 0.0f, 0.0f, 1.0f);
// Auto centre mesh based on vertex bounds.
glTranslatef(-x_mid_, -y_mid_, -z_mid_);
glDrawElements(GL_TRIANGLES, mesh_.num_indices, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO
}
void MeshWidget::openMesh(const string& filename) {
if (mesh_filename_ != filename) {
clearMeshData(mesh_);
glDeleteBuffersARB(1, &VertexVBOID);
glDeleteBuffersARB(1, &IndexVBOID);
ReadMsh(mesh_, filename);
// Create buffer objects here.
glGenBuffersARB(1, &VertexVBOID);
glBindBufferARB(GL_ARRAY_BUFFER, VertexVBOID);
glBufferDataARB(GL_ARRAY_BUFFER, sizeof(VertexAttributes)*mesh_.num_vertices, &mesh_.vertices[0], GL_STATIC_DRAW);
glGenBuffersARB(1, &IndexVBOID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t)*mesh_.num_indices, &mesh_.indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(12)); //The starting point of normals, 12 bytes away
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(24)); //The starting point of texcoords, 24 bytes away
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
if (startup_done_) updateGL();
}
}
void MeshWidget::openTexture(const string& filename) {
size_t dot = filename.find_last_of('.');
string ext(filename, dot, filename.size()); // 3rd parameter should be length of new string, but is internally clipped to end.
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glDeleteTextures(1, &texture_id_);
glGenTextures(1, &texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_id_);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (ext == ".dds") {
if (GLEE_EXT_texture_compression_s3tc) {
texture_id_ = SOIL_load_OGL_texture(filename.c_str(), SOIL_LOAD_AUTO, texture_id_, SOIL_FLAG_DDS_LOAD_DIRECT);
// SOIL takes care of calling glTexParams, glTexImage2D, etc.
yflip_texture_ = true;
} else {
//std::cout << "S3TC not supported on this graphics hardware." << std::endl;
// TODO: Error message in status bar?
}
} else {
QImage tex(filename.c_str());
tex = QGLWidget::convertToGLFormat(tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
yflip_texture_ = false;
}
updateUniforms();
if (startup_done_) updateGL();
}
void MeshWidget::updateUniforms() {
GLuint texture_flip_uniform = glGetUniformLocation(shader_prog_id_, "yflip");
glUniform1f(texture_flip_uniform, float(yflip_texture_ * 1.0f));
GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
glUniform1i(tex_loc, texture_id_);
}
And my shaders (there's still some junk in here because I was experimenting, but nothing that affects the output):
varying vec3 normal, lightDir, eyeVec;
uniform float yflip;
void main()
{
normal = gl_NormalMatrix * gl_Normal;
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
eyeVec = -vVertex;
gl_TexCoord[0].x = gl_MultiTexCoord0.x;
gl_TexCoord[1].x = gl_MultiTexCoord1.x;
if (yflip == 1.0) {
gl_TexCoord[0].y = 1 - gl_MultiTexCoord0.y;
gl_TexCoord[1].y = 1 - gl_MultiTexCoord1.y;
} else {
gl_TexCoord[0].y = gl_MultiTexCoord0.y;
gl_TexCoord[1].y = gl_MultiTexCoord1.y;
}
gl_Position = ftransform();
}
fragment shader:
varying vec3 normal, lightDir, eyeVec;
uniform sampler2D tex2;
void main (void)
{
vec4 texel = texture2D(tex2, gl_TexCoord[0].st);
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
vec3 N = normalize(normal);
vec3 L = normalize(lightDir);
float lambertTerm = dot(N,L);
if(lambertTerm > 0.0)
{
final_color += gl_LightSource[0].diffuse *
gl_FrontMaterial.diffuse *
lambertTerm;
vec3 E = normalize(eyeVec);
vec3 R = reflect(-L, N);
float specular = pow( max(dot(R, E), 0.0),
gl_FrontMaterial.shininess );
final_color += gl_LightSource[0].specular *
gl_FrontMaterial.specular *
specular;
}
gl_FragColor = final_color * texel;
}
glUniform1i(tex_loc, texture_id_);
The second parameter should specify ID of a texture unit(hint: glActiveTexture sets the currently active texture unit), not ID of particular texture object.