I'm trying to render a simple wire frame cube using JOGL.
However I am presented with a black screen, can anyone with more experience than me tell if I'm doing something wrong?
The shaders compile and throw no errors.
private Mat4 projectionMatrix;
//reference to the uniform MPV matrix in the vertex shader
private int mpvUnif;
//Holds the references to GL objects
private final int[] glPointers = new int[3];
private static final int VBO = 0;
private static final int INDEXBUFFER = 1;
private static final int VAO = 2;
private int shaderProgram;
private FloatBuffer vertexDataBuffer;
private ShortBuffer indexDataBuffer;
private float[] testCube = new float[] {
//Top
-1, 1, 1, //0
1, 1, 1, //1
-1, -1, 1, //2
1, -1, 1, //3
//Bottom
-1, 1, -1, //4
1, 1, -1, //5
-1, -1, -1, //6
1, -1, -1, //7
};
private short[] testCubeIndexes = new short[] {
0,1,2,3,
4,5,6,7,
0,1,4,5,
2,3,6,7,
0,2,4,6,
1,3,5,7
};
public GLController() {
this.vertexDataBuffer = FloatBuffer.wrap(testCube);
this.indexDataBuffer = ShortBuffer.wrap(testCubeIndexes);
}
#Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
shaderProgram = gl.glCreateProgram();
try {
InitializeVertexBuffer(gl);
InitializeVertexArrayObjects(gl);
initShaders(gl);
} catch (IOException e) {
e.printStackTrace();
}
gl.glPolygonMode(GL3.GL_FRONT_AND_BACK, GL3.GL_LINE);
gl.glFrontFace(GL3.GL_CW);
}
#Override
public void display(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindVertexArray(glPointers[VAO]);
gl.glDrawElements(GL3.GL_QUADS, indexDataBuffer.capacity(), GL3.GL_UNSIGNED_SHORT, 0);
gl.glBindVertexArray(0);
gl.glUseProgram(0);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL3 gl = drawable.getGL().getGL3();
mpvUnif = gl.glGetUniformLocation(shaderProgram, "MPV");
projectionMatrix = Matrices.perspective(60f, width/height, .1f, 100f);
gl.glUseProgram(shaderProgram);
gl.glUniformMatrix4fv(mpvUnif, 1, GLHelper.glBool(GL3.GL_FALSE), projectionMatrix.getBuffer());
gl.glUseProgram(0);
}
/**
* Called in GLEventListener.init()
* #param gl
*/
private void InitializeVertexBuffer(GL3 gl) {
gl.glGenBuffers(1, glPointers, VBO);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, glPointers[VBO]);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, GLHelper.sizeof(vertexDataBuffer), vertexDataBuffer, GL3.GL_STATIC_DRAW);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
gl.glGenBuffers(1, glPointers, INDEXBUFFER);
gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, glPointers[INDEXBUFFER]);
gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER, GLHelper.sizeof(indexDataBuffer), indexDataBuffer, GL3.GL_STATIC_DRAW);
gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0);
}
/**
* Called in GLEventListener.init()
* #param gl
*/
private void InitializeVertexArrayObjects(GL3 gl) {
gl.glGenVertexArrays(1, glPointers, VAO);
gl.glBindVertexArray(glPointers[VAO]);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, glPointers[VBO]);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 3, GL3.GL_FLOAT, GLHelper.glBool(GL3.GL_FALSE), 0, 0);
gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, glPointers[INDEXBUFFER]);
gl.glBindVertexArray(0);
}
My vertex shader:
#version 330
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
void main()
{
vec4 v = vec4(vertexPosition_modelspace, 1);
gl_Position = MVP * v;
}
This shader does draw something on the screen:
#version 330
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;//not used
void main()
{
gl_Position = vec4(vertexPosition_modelspace, 1);
}
My fragment shader:
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}
I'm feeling so silly, the main problem was that MVP in the shader was referenced as MPV! Thanks to gouessej for trying to help.
Related
I'm trying to show the normals of some vertices of the mesh when I select them but accordingly to the position of the cam these normals are displayed or not and the big problem is that they are displayed when they shouldn't (i.e. when i select vertices of the tibia but i'm looking at the calf so they should be hidden by the leg) and not displayed when they should be displayed.
I could be wrong but it's like some geometry of the model is drawn above the line. Moreover, if before calling the draw calls i disable the depth test it works (even if the problem of being showed when they shouldn't isn't resolved obviously). That's some images to give you an idea of what I mean.
WITH DEPTH TEST OFF:
DEPT TEST ON:
That's the code:
void StatusManager::Render() {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!animatedModel)
return;
Update();
// draw wireframe if enabled
if (wireframeEnabled)
DrawWireframe();
if (visualMode == Mode_Texture) {
// draw model
if (lightingMode == Mode_Flat)
DrawModel(modelFlatShader);
else if (lightingMode == Mode_Smooth)
DrawModel(modelSmoothShader);
else
DrawModel(modelNoLightShader);
}
else if (visualMode == Mode_CurrentBoneIDInfluence) {
DrawModel(currentBoneShader);
}
else if (visualMode == Mode_NumBones)
{
DrawModel(numBonesShader);
}
else
{
DrawModel(modelGreyShader);
}
// render selected vertices
DrawSelectedVertices();
if (!info.hitPoint)
return;
//DrawHotPoint();
if (selectionMode == Mode_Vertex)
DrawHoveredPoint();
if (selectionMode == Mode_Edge)
DrawHoveredLine();
if (selectionMode == Mode_Face)
DrawHoveredFace();
}
void StatusManager::DrawWireframe() {
wireframeShader.use();
glLineWidth(1.0f);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
wireframeShader.setMat4("modelView", modelView);
wireframeShader.setMat4("projection", projection);
// pass bones matrices to the shader
auto transforms = animator.GetFinalBoneMatrices();
for (int i = 0; i < transforms.size(); ++i)
wireframeShader.setMat4("finalBonesMatrices[" + std::to_string(i) + "]", transforms[i]);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
animatedModel.value().Draw(wireframeShader);
}
void StatusManager::DrawModel(Shader& modelShader) {
modelShader.use();
// model/view/projection transformations
modelShader.setMat4("modelView", camera.viewMatrix);
modelShader.setMat4("projection", projection);
if (visualMode == Mode_Texture)
modelShader.setVec3("light_pos", lightPos);
else if (visualMode == Mode_CurrentBoneIDInfluence)
modelShader.setInt("currentBoneID", currentBoneID);
// pass bones matrices to the shader
auto transforms = animator.GetFinalBoneMatrices();
for (int i = 0; i < transforms.size(); ++i)
modelShader.setMat4("finalBonesMatrices[" + std::to_string(i) + "]", transforms[i]);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
/*if (pause)
bakedModel.value().Draw(modelShader);
else*/
animatedModel.value().Draw(modelShader);
}
void StatusManager::DrawHoveredFace() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
//vertex
float hoveredVertices[9] = {
m.vertices[f.indices[0]].Position.x, m.vertices[f.indices[0]].Position.y, m.vertices[f.indices[0]].Position.z,
m.vertices[f.indices[1]].Position.x, m.vertices[f.indices[1]].Position.y, m.vertices[f.indices[1]].Position.z,
m.vertices[f.indices[2]].Position.x, m.vertices[f.indices[2]].Position.y, m.vertices[f.indices[2]].Position.z,
};
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(hoveredVertices), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glDrawArrays(GL_TRIANGLES, 0, 3);
//unbind
glBindVertexArray(0);
}
void StatusManager::DrawHoveredPoint() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
int index = getClosestVertexIndex(info.hitPoint.value(), m, f);
//vertex
float hoveredVertices[3] = { m.vertices[index].Position.x, m.vertices[index].Position.y, m.vertices[index].Position.z };
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(float), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glPointSize(8.0f);
glDrawArrays(GL_POINTS, 0, 1);
//unbind
glBindVertexArray(0);
}
void StatusManager::DrawHotPoint()
{
float hotVertices[3] = { hotPoint.x, hotPoint.y, hotPoint.z };
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(float), &hotVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glPointSize(8.0f);
glDrawArrays(GL_POINTS, 0, 1);
//unbind
glBindVertexArray(0);
}
void StatusManager::UpdateSelectedVertices()
{
selectedVertices.clear();
for (Vertex* v : selectedVerticesPointers)
selectedVertices.push_back(*v);
}
void StatusManager::DrawHoveredLine() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
auto line = getClosestLineIndex(info.hitPoint.value(), m, f);
//vertex
float hoveredVertices[6] = {
m.vertices[line.v1].Position.x, m.vertices[line.v1].Position.y, m.vertices[line.v1].Position.z,
m.vertices[line.v2].Position.x, m.vertices[line.v2].Position.y, m.vertices[line.v2].Position.z
};
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(hoveredVertices), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glLineWidth(3.0f);
glDrawArrays(GL_LINES, 0, 2);
glLineWidth(1.0f);
//unbind
glBindVertexArray(0);
}
normalShader just for completeness
VERTEX SHADER:
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 norm;
layout(location = 2) in ivec4 boneIds;
layout(location = 3) in vec4 weights;
layout(location = 4) in int numBones;
uniform mat4 projection;
uniform mat4 modelView;
uniform mat4 finalBonesMatrices[100];
out VS_OUT {
vec4 normal;
} vs_out;
void main()
{
mat4 cumulativeMatrix = mat4(1.0);
if (numBones>0)
cumulativeMatrix = mat4(0.0);
for(int i = 0 ; i < numBones ; i++)
{
cumulativeMatrix += (finalBonesMatrices[boneIds[i]] * weights[i]);
}
gl_Position = projection * modelView * cumulativeMatrix * vec4(pos, 1.0);
vs_out.normal = normalize(modelView * cumulativeMatrix * vec4(norm, 0.0));
}
GEOMETRY SHADER:
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;
uniform float normal_length;
in VS_OUT {
vec4 normal;
} gs_in[];
void main() {
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[0].gl_Position + gs_in[0].normal * normal_length;
EmitVertex();
EndPrimitive();
}
FRAGMENT SHADER:
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1, 0, 0, 1);
}
If you need other piece of code tell me and I'll provide it, but I think I posted all the code and images you need.
Ok I don't know how I didn't noticed it, but yes, the problem was that I wasn't applying the projection matrix to the normal vector. Thanks Spektre to point this out.
I've been trying OpenGL recently and are stuck again in an issue.
If in my program I set colors via uniforms, I can draw multiple vertex arrays with any color of my choice. But passing of two buffers to be generated for an vertex array object results in weird coloration, where 0 is for vertex location and 1 is for color.
My main function :
int main(){
Window window(960,540);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Reader read1("src/shaders/test.vert");
Reader read2("src/shaders/test.frag");
char * r1 = read1.getData();
char * r2 = read2.getData();
GLfloat vert[] = {
0, 0, 0,
0, 3, 0,
8, 3, 0,
8, 0, 0
};
GLushort indices[] = {
0,1,2,
2,3,0
};
GLfloat colors[] = {
1, 0, 1, 1,
1, 0, 1, 1,
1, 0, 1, 1,
1, 0, 1, 1,
};
VertexArray vao;
Buffer* vbo = new Buffer(vert, 4 * 4, 3);
vao.addBuffer(vbo, 0);
vao.addBuffer(new Buffer(colors,4 * 4 , 4), 1);
indexBuffer ibo(indices, 6);
Shader shader(r1, r2);
shader.enable();
shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));
shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
shader.setUniform4f("colour", vec4(0.2, 0.3, 0.8, 1));
while (!window.closed()){
window.clear();
double x, y;
x = window.getX();
y = window.getY();
shader.setUniform2f("light_pos", vec2((float)((x)*16.0f / 960.0f), (float)(9 - 9 * (y) / 540.0f)));
vao.bind();
ibo.bind();
shader.setUniform4f("colour", vec4(0.2, 0.3, 0.8, 1));
shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));
glDrawElements(GL_TRIANGLES, ibo.getCount(), GL_UNSIGNED_SHORT, 0);
ibo.unbind();
vao.unbind();
window.update();
}
return 0;
}
My vertex shaders :
#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
uniform mat4 pr_matrix ;
uniform mat4 vw_matrix = mat4(1.0f);
uniform mat4 ml_matrix = mat4(1.0f);
out DATA{
vec4 position;
vec4 color;
} vs_out;
out vec4 pos;
void main(){
gl_Position = pr_matrix * vw_matrix * ml_matrix * vec4(position,1) ;
vs_out.position = ml_matrix * vec4(position,1);
vs_out.color = color;
}
My fragment shaders :
#version 410 core
layout(location = 0) out vec4 color ;
uniform vec4 colour;
uniform vec2 light_pos;
in DATA{
vec4 position;
vec4 color;
} fs_in;
void main(){
float intensity = 1.0f / length(fs_in.position.xy - light_pos);
//color = fs_in.color * intensity;
color = fs_in.color * intensity;
}
My buffer class in case its needed to be corrected:
Buffer::Buffer(GLfloat *data, GLsizei count, GLuint compCountExt) : compCount (compCountExt) {
glGenBuffers(1, &bufferId);
glBindBuffer(GL_ARRAY_BUFFER,bufferId);
glBufferData(GL_ARRAY_BUFFER, count* sizeof(GLfloat), data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Buffer::bind() const {
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
}
void Buffer::unbind() const {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
EDIT:
code of the vertexArray Class:
VertexArray::VertexArray(){
glGenVertexArrays(1,&arrayID);
}
void VertexArray::bind() const{
glBindVertexArray(arrayID);
}
void VertexArray::unbind() const{
glBindVertexArray(0);
}
VertexArray::~VertexArray(){
}
void VertexArray::addBuffer(Buffer* buffer, GLuint index){
bind();
glBindBuffer(GL_ARRAY_BUFFER, arrayID);
glEnableVertexAttribArray(index);
glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);
buffer->unbind();
unbind();
}
there are calls to vertex attrib pointer in this class.
glVertexAttribPointer refers to the currently bound array buffer. This means you have to bind the array buffer befor you use glVertexAttribPointer:
void VertexArray::addBuffer(Buffer* buffer, GLuint index){
bind();
// glBindBuffer(GL_ARRAY_BUFFER, arrayID); <---- skip
buffer->bind(); // <---- bind the array buffer
glEnableVertexAttribArray(index);
glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);
buffer->unbind();
unbind();
}
See OpenGL 4.6 Specification - 10.3.9 Vertex Arrays in Buffer Objects:
A buffer object binding point is added to the client state associated with each
vertex array index. The commands that specify the locations and organizations of vertex arrays copy the buffer object name that is bound to ARRAY_BUFFER to
the binding point corresponding to the vertex array index being specified. For example, the VertexAttribPointer command copies the value of ARRAY_BUFFER_BINDING.
the problem is in the title.
Console error
LWJGL Version: 3.0.0 build 90
GLFW Version: 3.2.0 Win32 WGL EGL VisualC DLL
OpenGL Version: 4.0.0 NVIDIA 372.70
java.lang.Exception: Can't find uniform: lightColor
at com.ms.shaders.ShaderProgram.getUniformLocation(ShaderProgram.java:50)
at com.ms.shaders.Shaders.createUniforms(Shaders.java:32)
ShaderProgram
public class ShaderProgram {
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
private Map<String, Integer> uniforms;
public ShaderProgram() {
uniforms = new HashMap<>();
}
public void createProgram() throws Exception {
programID = glCreateProgram();
if(programID == 0) {
throw new Exception("Failed to create program");
}
}
public void createShaders(String vertexFile, String fragmentFile) throws Exception {
vertexShaderID = shadersLoader(vertexFile, GL_VERTEX_SHADER);
}
protected void bindAttribute(int attribute, String name) {
glBindAttribLocation(programID, attribute, name);
}
public void getUniformLocation(String uniform) throws Exception {
int uniformLocation = glGetUniformLocation(programID, uniform);
if(uniformLocation < 0) {
throw new Exception("Can't find uniform: " + uniform);
}
uniforms.put(uniform, uniformLocation);
}
public void floatUniforms(String uniform, float value) {
glUniform1f(uniforms.get(uniform), value);
}
public void intUniforms(String uniform, int value) {
glUniform1i(uniforms.get(uniform), value);
}
public void booleanUniforms(String uniform, boolean value) {
float load = 0;
if(value) {
load = 1;
}
glUniform1f(uniforms.get(uniform), load);
}
public void vectorUniforms(String uniform, Vector3f value) {
glUniform3f(uniforms.get(uniform), value.x, value.y, value.z);
}
public void matrixUniforms(String uniform, Matrix4f value) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
value.get(buffer);
glUniformMatrix4fv(uniforms.get(uniform), false, buffer);
}
public int shadersLoader(String shader, int type) throws Exception {
int shaderID = glCreateShader(type);
glShaderSource(shaderID, shader);
glCompileShader(shaderID);
if(glGetShaderi(shaderID, GL_COMPILE_STATUS) == 0) {
throw new Exception("Failed to compile Shader: " + glGetShaderInfoLog(shaderID, 1024));
}
glAttachShader(programID, shaderID);
return shaderID;
}
public void linkProgram() throws Exception {
glLinkProgram(programID);
if(glGetProgrami(programID, GL_LINK_STATUS) == 0) {
throw new Exception("Failed to link program: " + glGetProgramInfoLog(programID, 1024));
}
glValidateProgram(programID);
if(glGetProgrami(programID, GL_VALIDATE_STATUS) == 0) {
throw new Exception("Failed to validate program: " + glGetProgramInfoLog(programID, 1024));
}
}
public void bind() {
glUseProgram(programID);
}
public void unbind() {
glUseProgram(0);
}
public void cleanUp() {
unbind();
if(programID != 0) {
if(vertexShaderID != 0) {
glDetachShader(programID, vertexShaderID);
glDeleteShader(vertexShaderID);
}
if(fragmentShaderID != 0) {
glDetachShader(programID, fragmentShaderID);
glDeleteShader(fragmentShaderID);
}
glDeleteProgram(programID);
}
}
}
Shaders
public class Shaders extends ShaderProgram {
private static final String VERTEX_SHADER = "vertexShader.txt";
private static final String FRAGMENT_SHADER = "fragmentShader.txt";
public void init() throws Exception {
createProgram();
createShaders(FileLoader.loadResources(VERTEX_SHADER), FileLoader.loadResources(FRAGMENT_SHADER));
linkProgram();
createUniforms();
}
public void bindAttributes() {
bindAttribute(0, "position");
bindAttribute(1, "textureCoords");
bindAttribute(2, "normal");
}
public void createUniforms() throws Exception {
getUniformLocation("transformationMatrix");
getUniformLocation("projectionMatrix");
getUniformLocation("viewMatrix");
getUniformLocation("lightPosition");
getUniformLocation("lightColor");
getUniformLocation("shineDamper");
getUniformLocation("reflectivity");
}
}
fragmentShader.txt
#version 400 core
in vec2 outTextureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCameraVector;
out vec4 outColor;
uniform sampler2D textureSampler;
uniform vec3 lightColor;
uniform float shineDamper;
uniform float reflectivity;
void main()
{
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDotl = dot(unitNormal, unitLightVector);
float brightness = max(nDotl, 0.2);
vec3 diffuse = brightness * lightColor;
vec3 unitVectorToCamera = normalize(toCameraVector);
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);
float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
specularFactor = max(specularFactor, 0.0);
float dampFactor = pow(specularFactor, shineDamper);
vec3 finalSpecular = dampFactor * reflectivity * lightColor;
outColor = vec4(diffuse, 1.0) * texture(textureSampler, outTextureCoords) + vec4(finalSpecular, 1.0);
}
If i try to remove lightColor uniform the error switch in the shineDamper uniform.
EDITED
If i put all in the Renderer class the problem don't exist... Why?
This is the class where I set uniforms:
UniformCreation
public class UniformsCreation {
private Transformation transformation;
private ShaderProgram shaders;
private float FOV = (float) Math.toRadians(60.0f);
private float zNEAR = 0.01f;
private float zFAR = 1000.0f;
public UniformsCreation() {
transformation = new Transformation();
shaders = new ShaderProgram();
}
public void renderer(Entity[] entity, Camera camera, Light light) {
createProjectionMatrix();
createTransformationMatrix(entity);
createViewMatrix(camera);
createLight(light, Texture.getShineDamper(), Texture.getReflection());
}
public Matrix4f createProjectionMatrix() {
Matrix4f projectionMatrix = new Matrix4f();
projectionMatrix = transformation.createProjectionMatrix(
FOV,
Main.getWIDTH(),
Main.getHEIGHT(),
zNEAR,
zFAR);
shaders.matrixUniforms("projectionMatrix", projectionMatrix);
return projectionMatrix;
}
public Matrix4f createTransformationMatrix(Entity[] entity) {
Matrix4f transformationMatrix = new Matrix4f();
for(Entity entities : entity) {
transformationMatrix = transformation.createTransformationMatrix(
entities.getPosition(),
entities.getRotation(),
entities.getScale());
shaders.matrixUniforms("transformationMatrix", transformationMatrix);
entities.getMesh().render();
}
return transformationMatrix;
}
public Matrix4f createViewMatrix(Camera camera) {
Matrix4f viewMatrix = new Matrix4f();
viewMatrix = transformation.createViewMatrix(camera);
shaders.matrixUniforms("viewMatrix", viewMatrix);
return viewMatrix;
}
public void createLight(Light light, float damper, float reflectivity) {
shaders.vectorUniforms("lightPosition", light.getPosition());
shaders.vectorUniforms("lightColor", light.getColor());
shaders.floatUniforms("shineDamper", damper);
shaders.floatUniforms("reflectivity", reflectivity);
}
}
If I remove the lightColor, shineDamper and reflectivity uniforms the error is:
java.lang.NullPointerException
at com.ms.shaders.ShaderProgram.matrixUniforms(ShaderProgram.java:83)
at com.ms.utils.UniformsCreation.createProjectionMatrix(UniformsCreation.java:46)
at com.ms.utils.UniformsCreation.renderer(UniformsCreation.java:29)
at com.ms.renderer.Renderer.render(Renderer.java:42)
at com.ms.MineSmooth.gameLoop(MineSmooth.java:93)
at com.ms.MineSmooth.run(MineSmooth.java:56)
at java.lang.Thread.run(Unknown Source)
Negative uniform locations are perfectly cromulent:
Although not strictly a mistake, some wonder why glGetUniformLocation​
returns -1. If there is a uniform that you are not using, the driver
will optimize your uniform out. Drivers are really good at optimizing
code. If you are using your uniform, but none of the values computed
from that uniform contribute to any output from the shader (directly
or indirectly), the uniform will usually be optimized out.
Typically this is not a problem, since if you pass -1 instead of a
valid uniform location to the glUniform​ calls, they will quietly do
nothing anyway. But you will also get -1 if you misspell the variable
name to glGetUniformLocation​, so keep this in mind.
Enumerate uniform names via the shader introspection API to check for spelling mistakes.
I'm attempting to render a triangle using VBOs in OpenGL via C++.
First, I identify my variables:
CBuint _vao;
CBuint _vbo;
CBuint _ebo;
struct Vertex
{
CBfloat position[3];
};
Then, I set the positions for each vertex to form a geometrical triangle:
Vertex v[3];
v[0].position[0] = 0.5f;
v[0].position[1] = 0.5f;
v[0].position[2] = 0.0f;
v[1].position[0] = 0.5f;
v[1].position[1] = -0.5f;
v[1].position[2] = 0.0f;
v[2].position[0] = -0.5f;
v[2].position[1] = -0.5f;
v[2].position[2] = 0.0f;
Simple enough, right?
Then, I declare my indices for the EBO/IBO:
unsigned short i[] =
{
0, 1, 2
};
Now that I have all the attribute data needed for buffering, I bind the VAO as well as the VBOs:
// Generate vertex elements
glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ebo);
// VAO
glBindVertexArray(_vao);
// VBO
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 9, &v, GL_STATIC_DRAW);
// EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * 3, &i, GL_STATIC_DRAW);
// Location 0 - Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glBindVertexArray(0);
Next, I render them:
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
I then use the vertex shader:
#version 330 core
// Vertex attributes
layout(location = 0) in vec3 position;
// Node parses
out vec3 Fragpos;
// Uniforms
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
// Vertex loop
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
Fragpos = vec3(model * vec4(position, 1.0f));
}
To simply calculate the model position as well as the camera view. The fragment shader is again, quite simplistic:
#version 330 core
// Node parses
out vec4 color;
in vec3 Fragpos;
// Camera data
uniform vec3 view_loc;
// Global uniforms
uniform struct GLOBAL
{
float ambient_coefficient;
vec3 ambient_colour;
} _global;
// Main loop
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
The uniforms work perfectly fine as I've been using this shader code for previous projects. So what could the problem be? The triangle simply does not render. I can't think of anything that's causing this, any ideas?
Edit: Just to narrow things down, I also use these variables to handle the model matrix that are being parsed to and from the vertex shader:
CBuint _u_model;
mat4 _model;
vec3 _position;
vec4 _rotation;
vec3 _scale;
Then inside the constructor, I initialize the variables like so:
_model = mat4::identity();
_position = vec3(0.0f, 0.0f, 0.0f);
_rotation = vec4(0.0f, 1.0f, 0.0f, 0.0f);
_scale = vec3(1.0f, 1.0f, 1.0f);
_u_model = glGetUniformLocation(shader->_program, "model");
And finally, I update the model matrix using this formula:
_model = translate(_position) *
rotate(_rotation.data[0], _rotation.data[1], _rotation.data[2], _rotation.data[3]) *
scale(_scale);
Edit 2: This is the camera class I use for the MVP:
class Camera : public object
{
private:
CBbool _director;
CBfloat _fov;
CBfloat _near;
CBfloat _far;
CBfloat _speed;
Math::vec3 _front;
Math::vec3 _up;
Math::mat4 _projection;
Math::mat4 _view;
CBuint _u_projection;
CBuint _u_view;
public:
Camera(Shader* shader, Math::vec3 pos, float fov, float n, float f, bool dir) : _speed(5.0f)
{
_model = Math::mat4::identity();
_projection = Math::mat4::identity();
_view = Math::mat4::identity();
_position = pos;
_fov = fov;
_near = n;
_far = f;
_director = dir;
_front = vec3(0.0f, 0.0f, -1.0f);
_up = vec3(0.0f, 1.0f, 0.0f);
_u_projection = glGetUniformLocation(shader->_program, "projection");
_u_view = glGetUniformLocation(shader->_program, "view");
_u_model = glGetUniformLocation(shader->_program, "view_loc");
}
~Camera() {}
inline CBbool isDirector() { return _director; }
inline void forward(double delta) { _position.data[2] -= _speed * (float)delta; }
inline void back(double delta) { _position.data[2] += _speed * (float)delta; }
inline void left(double delta) { _position.data[0] -= _speed * (float)delta; }
inline void right(double delta) { _position.data[0] += _speed * (float)delta; }
inline void up(double delta) { _position.data[1] += _speed * (float)delta; }
inline void down(double delta) { _position.data[1] -= _speed * (float)delta; }
virtual void update(double delta)
{
_view = Math::lookat(_position, _position + _front, _up);
_projection = Math::perspective(_fov, 900.0f / 600.0f, _near, _far);
}
virtual void render()
{
glUniformMatrix4fv(_u_view, 1, GL_FALSE, _view);
glUniformMatrix4fv(_u_projection, 1, GL_FALSE, _projection);
glUniform3f(_u_model, _position.data[0], _position.data[1], _position.data[2]);
}
};
As Amadeus mentioned, I simply had to use gl_Position = vec4(position, 1.0f); for it to render. No idea why, but now's the time to find out! Thanks for your time.
I'm having trouble getting phong shading to look right. I'm pretty sure there's something wrong with either my OpenGL calls, or the way I'm loading my normals, but I guess it could be something else since 3D graphics and Assimp are both still very new to me. When trying to load .obj/.mtl files, the problems I'm seeing are:
The models seem to be lit too intensely (less phong-style and more completely washed out, too bright).
Faces that are lit seem to be lit equally all over (with the exception of a specular highlight showing only when the light source position is moved to be practically right on top of the model)
Because of problems 1 and 2, spheres look very wrong:
picture of sphere
And things with larger faces look (less-noticeably) wrong too:
picture of cube
I could be wrong, but to me this doesn't look like proper phong shading.
Here's the code that I think might be relevant (I can post more if necessary):
file: assimpRenderer.cpp
#include "assimpRenderer.hpp"
namespace def
{
assimpRenderer::assimpRenderer(std::string modelFilename, float modelScale)
{
initSFML();
initOpenGL();
if (assImport(modelFilename)) // if modelFile loaded successfully
{
initScene();
mainLoop(modelScale);
shutdownScene();
}
shutdownOpenGL();
shutdownSFML();
}
assimpRenderer::~assimpRenderer()
{
}
void assimpRenderer::initSFML()
{
windowWidth = 800;
windowHeight = 600;
settings.majorVersion = 3;
settings.minorVersion = 3;
app = NULL;
shader = NULL;
app = new sf::Window(sf::VideoMode(windowWidth,windowHeight,32), "OpenGL 3.x Window", sf::Style::Default, settings);
app->setFramerateLimit(240);
app->setActive();
return;
}
void assimpRenderer::shutdownSFML()
{
delete app;
return;
}
void assimpRenderer::initOpenGL()
{
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
}
// check the OpenGL context version that's currently in use
int glVersion[2] = {-1, -1};
glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]); // get the OpenGL Major version
glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]); // get the OpenGL Minor version
std::cout << "Using OpenGL Version: " << glVersion[0] << "." << glVersion[1] << std::endl;
return;
}
void assimpRenderer::shutdownOpenGL()
{
return;
}
void assimpRenderer::initScene()
{
// allocate heap space for VAOs, VBOs, and IBOs
vaoID = new GLuint[scene->mNumMeshes];
vboID = new GLuint[scene->mNumMeshes*2];
iboID = new GLuint[scene->mNumMeshes];
glClearColor(0.4f, 0.6f, 0.9f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
shader = new Shader("shader.vert", "shader.frag");
projectionMatrix = glm::perspective(60.0f, (float)windowWidth / (float)windowHeight, 0.1f, 100.0f);
rot = 0.0f;
rotSpeed = 50.0f;
faceIndex = 0;
colorArrayA = NULL;
colorArrayD = NULL;
colorArrayS = NULL;
normalArray = NULL;
genVAOs();
return;
}
void assimpRenderer::shutdownScene()
{
delete [] iboID;
delete [] vboID;
delete [] vaoID;
delete shader;
}
void assimpRenderer::renderScene(float modelScale)
{
sf::Time elapsedTime = clock.getElapsedTime();
clock.restart();
if (rot > 360.0f)
rot = 0.0f;
rot += rotSpeed * elapsedTime.asSeconds();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -3.0f, -10.0f)); // move back a bit
modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(modelScale)); // scale model
modelMatrix = glm::rotate(modelMatrix, rot, glm::vec3(0, 1, 0));
//modelMatrix = glm::rotate(modelMatrix, 25.0f, glm::vec3(0, 1, 0));
glm::vec3 lightPosition( 0.0f, -100.0f, 0.0f );
float lightPositionArray[3];
lightPositionArray[0] = lightPosition[0];
lightPositionArray[1] = lightPosition[1];
lightPositionArray[2] = lightPosition[2];
shader->bind();
int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix");
int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix");
int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix");
int ambientLocation = glGetUniformLocation(shader->id(), "ambientColor");
int diffuseLocation = glGetUniformLocation(shader->id(), "diffuseColor");
int specularLocation = glGetUniformLocation(shader->id(), "specularColor");
int lightPositionLocation = glGetUniformLocation(shader->id(), "lightPosition");
int normalMatrixLocation = glGetUniformLocation(shader->id(), "normalMatrix");
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]);
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]);
glUniform3fv(lightPositionLocation, 1, lightPositionArray);
for (unsigned int i = 0; i < scene->mNumMeshes; i++)
{
colorArrayA = new float[3];
colorArrayD = new float[3];
colorArrayS = new float[3];
material = scene->mMaterials[scene->mNumMaterials-1];
normalArray = new float[scene->mMeshes[i]->mNumVertices * 3];
unsigned int normalIndex = 0;
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
normalIndex = 0;
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray);
aiColor3D ambient(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
aiColor3D diffuse(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
aiColor3D specular(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
colorArrayA[0] = ambient.r; colorArrayA[1] = ambient.g; colorArrayA[2] = ambient.b;
colorArrayD[0] = diffuse.r; colorArrayD[1] = diffuse.g; colorArrayD[2] = diffuse.b;
colorArrayS[0] = specular.r; colorArrayS[1] = specular.g; colorArrayS[2] = specular.b;
// bind color for each mesh
glUniform3fv(ambientLocation, 1, colorArrayA);
glUniform3fv(diffuseLocation, 1, colorArrayD);
glUniform3fv(specularLocation, 1, colorArrayS);
// render all meshes
glBindVertexArray(vaoID[i]); // bind our VAO
glDrawElements(GL_TRIANGLES, scene->mMeshes[i]->mNumFaces*3, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // unbind our VAO
delete [] normalArray;
delete [] colorArrayA;
delete [] colorArrayD;
delete [] colorArrayS;
}
shader->unbind();
app->display();
return;
}
void assimpRenderer::handleEvents()
{
sf::Event event;
while (app->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
app->close();
}
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
{
app->close();
}
if (event.type == sf::Event::Resized)
{
glViewport(0, 0, event.size.width, event.size.height);
}
}
return;
}
void assimpRenderer::mainLoop(float modelScale)
{
while (app->isOpen())
{
renderScene(modelScale);
handleEvents();
}
}
bool assimpRenderer::assImport(const std::string& pFile)
{
// read the file with some example postprocessing
scene = importer.ReadFile(pFile,
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType);
// if the import failed, report it
if (!scene)
{
std::cerr << "Error: " << importer.GetErrorString() << std::endl;
return false;
}
return true;
}
void assimpRenderer::genVAOs()
{
int vboIndex = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; i++, vboIndex+=2)
{
mesh = scene->mMeshes[i];
indexArray = new unsigned int[mesh->mNumFaces * sizeof(unsigned int) * 3];
// convert assimp faces format to array
faceIndex = 0;
for (unsigned int t = 0; t < mesh->mNumFaces; ++t)
{
const struct aiFace* face = &mesh->mFaces[t];
std::memcpy(&indexArray[faceIndex], face->mIndices, sizeof(float) * 3);
faceIndex += 3;
}
// generate VAO
glGenVertexArrays(1, &vaoID[i]);
glBindVertexArray(vaoID[i]);
// generate IBO for faces
glGenBuffers(1, &iboID[i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * mesh->mNumFaces * 3, indexArray, GL_STATIC_DRAW);
// generate VBO for vertices
if (mesh->HasPositions())
{
glGenBuffers(1, &vboID[vboIndex]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex]);
glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, mesh->mVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)0);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
// generate VBO for normals
if (mesh->HasNormals())
{
normalArray = new float[scene->mMeshes[i]->mNumVertices * 3];
unsigned int normalIndex = 0;
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
normalIndex = 0;
glGenBuffers(1, &vboID[vboIndex+1]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex+1]);
glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, normalArray, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)1);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
delete [] normalArray;
}
// tex coord stuff goes here
// unbind buffers
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
delete [] indexArray;
}
vboIndex = 0;
return;
}
}
file: shader.vert
#version 150 core
in vec3 in_Position;
in vec3 in_Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform vec3 lightPosition;
uniform mat3 normalMatrix;
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
void main()
{
// derive MVP and MV matrices
mat4 modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix;
mat4 modelViewMatrix = viewMatrix * modelMatrix;
// get surface normal in eye coordinates
vVaryingNormal = normalMatrix * in_Normal;
// get vertex position in eye coordinates
vec4 vPosition4 = modelViewMatrix * vec4(in_Position, 1.0);
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// get vector to light source
vVaryingLightDir = normalize(lightPosition - vPosition3);
// Set the position of the current vertex
gl_Position = modelViewProjectionMatrix * vec4(in_Position, 1.0);
}
file: shader.frag
#version 150 core
out vec4 out_Color;
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform vec3 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
void main()
{
// dot product gives us diffuse intensity
float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
// multiply intensity by diffuse color, force alpha to 1.0
out_Color = vec4(diff * diffuseColor, 1.0);
// add in ambient light
out_Color += vec4(ambientColor, 1.0);
// specular light
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if (diff != 0)
{
float fSpec = pow(spec, 128.0);
// Set the output color of our current pixel
out_Color.rgb += vec3(fSpec, fSpec, fSpec);
}
}
I know it's a lot to look through, but I'm putting most of the code up so as not to assume where the problem is.
Are you doing the right thing for the normal matrix? This looks quite bizarre to me.
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray);
Why does the normalMatrix have anything to do with the vertices of the mesh? It should be identical to your modelMatrix (provided that you're not doing any non-uniform scaling).