GreatCorn
GreatCorn

Reputation: 101

glDrawArrays and glVertexAttribPointer

I'm trying to learn OpenGL and GLSL. I'm trying to draw an imported model, which is stored in three arrays (vertices - array of TVector3, which is a record/struct with X, Y, Z: single/float; normals - array of TVector3; UVs - array of TVector2). The model was drawn fine without using shaders and using old calls such as glTexCoord, glNormal and glVertex. I switched to glDrawArrays because everything is always deprecated and trying to use shaders and glTexCoordPointer didn't work as the layout (location = 2) contained either incorrect UV mapping or none at all (texture is still there because the mesh is given coloring) and glTexCoordPointer didn't affect it at all. However, when trying to use the glVertexAttribPointer approach found on this tutorial nothing is drawn at all. I convert the three arrays into one array of single, but still to no avail. Trying to use glDrawElements results in a SIGSEGV, because I have no indices to provide (also I've read it's slower than glDrawArrays).

I'm lost, is there anything I'm doing wrong? Maybe I'm missing something? Are there any ways to pass arrays of TVectorX without combining them all into one?

My code (Object Pascal, OpenGL 4.3):

type
  TVector2 = record
    public
      X, Y: single;
      {...}
  end;  
  TVector3 = record
    private                                     
      {...}
    public
      X, Y, Z: single; 
      {...}
  end;

var
  MeshArray: array of single;  
  VertexArray, VertexBuffer: longword;    

{Mesh initialization code:}

SetLength(MeshArray, Length(Vertices)*8);
for i:=1 to Length(Vertices) do begin
  j := (i-1)*8;
  MeshArray[ j ] := Vertices[i-1].X;
  MeshArray[j+1] := Vertices[i-1].Y;
  MeshArray[j+2] := Vertices[i-1].Z;
  MeshArray[j+3] := Normals[i-1].X;
  MeshArray[j+4] := Normals[i-1].Y;
  MeshArray[j+5] := Normals[i-1].Z;
  MeshArray[j+6] := UVs[i-1].X;
  MeshArray[j+7] := UVs[i-1].Y;
end;
glGenVertexArrays(1, @VertexArray);
glGenBuffers(1, @VertexBuffer);

glBindVertexArray(VertexArray);

glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, SizeOf(MeshArray), @MeshArray, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, SizeOf(single) * 8, PChar(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, SizeOf(single) * 8, PChar(3 * SizeOf(single)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, SizeOf(single) * 8, PChar(6 * SizeOf(single)));
glEnableVertexAttribArray(2);  

{Drawing code:}

glActiveTexture(GL_TEXTURE0);  //Not necessary
glBindTexture(GL_TEXTURE_2D, mat.Albedo.Data); 

glUseProgram(mat.ShaderProgram);
//Draws model correctly, but without UV when using glVertexPointer(3, GL_FLOAT, 0, @Vertices[0]);

glBindVertexArray(VertexArray);      
glDrawArrays(GL_TRIANGLES, 0, Length(Vertices));   

Vertex shader (MatVertex is just the object and camera matrix):

#version 430 core

layout (location = 0) in vec3 Vertex;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec2 UV;

out vec3 outVertex;
out vec3 outNormal;
out vec2 outUV;

uniform mat4 MatVertex;

void main(){
    gl_Position = vec4(Vertex, 1.0) * MatVertex;
    outVertex = Vertex;
    outNormal = Normal;
    outUV = UV;
}

Fragment shader:

#version 430 core

in vec3 outVertex;
in vec3 outNormal;
in vec2 outUV;

out vec3 color;

uniform sampler2D albedoTex;

void main(){
    color = texture(albedoTex, outUV).rgb;
}

enter image description here

Upvotes: 1

Views: 653

Answers (1)

Rabbid76
Rabbid76

Reputation: 210878

The vector needs to be multiplied to the matrix from the tight (see GLSL Programming/Vector and Matrix Operations):

gl_Position = vec4(Vertex, 1.0) * MatVertex;

gl_Position = MatVertex * vec4(Vertex, 1.0);

Upvotes: 1

Related Questions