Reputation: 101
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;
}
Upvotes: 1
Views: 653
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