Dear People.
I`m currently creating a little 2D engine for the IOS, and I`m experiencing some dificulties with shaders. In fact, It is the first time I program an engine using the programable pipeline of OPEnGL, and than I think I´m doing something wrong.
My engine works with a simple mesh that are used for all visible objects. This mesh is composed by two triangles that are arranged as a quad. I `m sure that the vertex processing is ok, because I get the objects drawn correctly without texturing.
Unfortunately, the texturing stuff seems to have a problem. I load an image from an application resource, and than put it on a memmory buffer. This biffer is passed to the shader as uniform. Texture coordinates (uv)
are passed as attributes. I use glDrawElements to perform drawing.
The mesh is drawn correctly, but I have no texture . The resulting color is the same for all object pixels. I`m sure that the image is ok because I checked the image buffer contents before drawing.
I put the code below. Maybe some of you can see what I´m missing. It is the method I use to draw each object. the method is full of my engine stuff (MY_ENGINE prefix). I also put the shaders
void MY_ENGINE_Graphics::DrawObject(MY_ENGINE_Drawable *drawable)
{
Struct_3D_Mesh* mesh;
MY_ENGINE_Shader* shader;
MY_ENGINE_Transform *transform;
StructPose * pose;
U8 enabledShaderInputVariables;
StructResourceID *shaderResource;
GLint uniformLocations[NUM_UNIFORMS];
U8 enabedShaderUniformVariables;
GLuint shaderProgram;
GLKMatrix4 modelViewMatrix;
GLKMatrix4 modelViewProjectionMatrix;
GLKMatrix3 normalMatrix;
MY_ENGINE_Sprite * sprite;
MY_ENGINE_TargaImage *colorMap = NULL;;
MY_ENGINE_TargaImage *effectMap = NULL;
shaderResource = drawable->GetShaderResourceId();
if(shaderResource == NULL)
return;
shader = (MY_ENGINE_Shader*)mResourceProvider->GetResource(shaderResource);
if(shader == NULL)
return;
shaderProgram = shader->GetShaderProgram();
if(shaderProgram == 0)
return;
enabedShaderUniformVariables = shader->GetEnabledUniformVariables();
enabledShaderInputVariables = shader->GetEnabledInputVariables();
if(shaderProgram != mLastShader)
{
glUseProgram(shaderProgram);
mLastShader = shaderProgram;
}
mesh = (Struct_3D_Mesh*)mResourceProvider->GetResource( drawable->GetMesh());
if(mesh == NULL)
return;
sprite = (MY_ENGINE_Sprite *)mResourceProvider->GetResource(drawable->GetCurrentFrame());
if(sprite != NULL)
{
colorMap = sprite->GetMap(MY_ENGINE_COLOR_MAP);
effectMap = sprite->GetMap(MY_ENGINE_EFFECT_MAP);
if(colorMap)
{
//Bind and configure color texture
glActiveTexture(MY_ENGINE_COLOR_MAP);
glBindTexture(GL_TEXTURE_2D, mTextureNames[MY_ENGINE_COLOR_MAP]);
if(colorMap->colorDepth == 32)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,(GLsizei)colorMap->width,(GLsizei)colorMap->height, 0, GL_RGBA, GL_UNSIGNED_BYTE,colorMap->pImageData);
else if(colorMap->colorDepth == 24)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,(GLsizei)colorMap->width,(GLsizei)colorMap->height, 0, GL_RGB, GL_UNSIGNED_BYTE,colorMap->pImageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
if(effectMap)
{
//Bind and configure effect texture
glActiveTexture(MY_ENGINE_EFFECT_MAP);
glBindTexture(GL_TEXTURE_2D, mTextureNames[MY_ENGINE_EFFECT_MAP]);
if(effectMap->colorDepth == 32)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,(GLsizei)effectMap->width,(GLsizei)effectMap->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, effectMap->pImageData);
else if(effectMap->colorDepth ==24)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,(GLsizei)effectMap->width,(GLsizei)effectMap->height, 0, GL_RGB, GL_UNSIGNED_BYTE, effectMap->pImageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
}
if(enabledShaderInputVariables & MY_ENGINE_ENABLE_VertexPosition)
{
glBindBuffer(GL_ARRAY_BUFFER,mVboHandles[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER,VERTEX_BUFFER_SIZE(mesh->numVertex),mesh->vertexBuffer,GL_STATIC_DRAW);
glVertexAttribPointer(VBO_VERTEX,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(VBO_VERTEX);
}
if(enabledShaderInputVariables & MY_ENGINE_ENABLE_NormalVector)
{
//Normal Vectors:
glBindBuffer(GL_ARRAY_BUFFER,mVboHandles[VBO_NORMAL]);
glBufferData(GL_ARRAY_BUFFER,NORMAL_BUFFER_SIZE(mesh->numNormals),mesh->normalBuffer,GL_STATIC_DRAW);
glVertexAttribPointer(VBO_NORMAL,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(VBO_NORMAL);
}
if(enabledShaderInputVariables & MY_ENGINE_ENABLE_UV)
{
//uv Vectors:
glBindBuffer(GL_ARRAY_BUFFER,mVboHandles[VBO_UV]);
glBufferData(GL_ARRAY_BUFFER,UV_BUFFER_SIZE(mesh->numUv),mesh->uvBuffer,GL_STATIC_DRAW);
glVertexAttribPointer(VBO_UV,2,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(VBO_UV);
}
/*
else if(enabledShaderInputVariables & MY_ENGINE_ENABLE_VertexColor)
{
//Color :
glBindBuffer(GL_ARRAY_BUFFER,mVboHandles[VBO_COLOR]);
glBufferData(GL_ARRAY_BUFFER,_BUFFER_SIZE(mesh->numNormals),mesh->normalBuffer,GL_STATIC_DRAW);
glVertexAttribPointer(VBO_COLOR,3,GL_FLOAT,GL_FALSE,0,0);
}*/
//Collect uniform locations from shader
for(U8 i = 0;i < NUM_UNIFORMS;i++)
{
uniformLocations[i] = -1;
if(enabedShaderUniformVariables & mUniformMasks[i])
{
uniformLocations[i] = glGetUniformLocation(shaderProgram,*mUniformNames[i]);
}
}
//Color map uniform
if(enabedShaderUniformVariables & mUniformMasks[UNIFORM_COLOR_MAP])
{
glUniform1i(uniformLocations[UNIFORM_COLOR_MAP],MY_ENGINE_COLOR_MAP); //Passing the index of the texture unity to be used
}
//effect map uniform
if(enabedShaderUniformVariables & mUniformMasks[UNIFORM_EFFECT_MAP])
{
glUniform1i(uniformLocations[UNIFORM_EFFECT_MAP], MY_ENGINE_EFFECT_MAP); //Passing the index of the texture unity to be used
}
transform = (MY_ENGINE_Transform*)drawable->GetTransform();
pose = transform->GetPose();
modelViewMatrix = GLKMatrix4MakeTranslation(pose->posX,pose->posY,0);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix,pose->angle,0,0,1);
modelViewMatrix = GLKMatrix4Multiply(mBaseModelViewMatrix, modelViewMatrix);
normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
modelViewProjectionMatrix = GLKMatrix4Multiply(mProjectionMatrix, modelViewMatrix);
if(enabedShaderUniformVariables & mUniformMasks[UNIFORM_MODELVIEWPROJECTION_MATRIX])
{
glUniformMatrix4fv(uniformLocations[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, modelViewProjectionMatrix.m);
}
if(enabedShaderUniformVariables & mUniformMasks[UNIFORM_NORMAL_MATRIX])
{
glUniformMatrix3fv(uniformLocations[UNIFORM_NORMAL_MATRIX], 1, 0, normalMatrix.m);
}
//At last, Draw!
glDrawElements(GL_TRIANGLES,mesh->numFaces *3 , GL_UNSIGNED_SHORT, mesh->faceBuffer);
}
The shaders:
Vertex shader
attribute vec4 position;
uniform mat4 modelViewProjectionMatrix;
attribute vec2 uv;
varying vec2 fragTextCoord;
void main()"\
{
gl_Position = modelViewProjectionMatrix *position;
fragTextCoord = uv;
}
Fragment shader
uniform sampler2D colorMap;
varying mediump vec2 fragTextCoord;
void main()
{
gl_FragColor = texture2D(colorMap, fragTextCoord);
}
Note that I´m using only one texture: The ColorMap. The effect map is aimend for effects like bump map and so on. But it is not been used and the shaders are not referencing it.