Hello. I'm trying to make my own rendering pipeline, but can't get it working. I was reading many articles and trying to make my own, but I got problem and I think it is in modelViewProjection matrix calculation. Here is my codes:
public class Main {
//Triangle
private FloatBuffer verticesData;
private final int strideBytes = 7 * 4;
private final int positionOffset = 0;
private final int positionSize = 3;
private final int colorOffset = 3;
private final int colorSize = 4;
public Main(){
try{
Display.setDisplayMode(new DisplayMode(640, 480));
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
System.exit(0);
}
initOpenGL();
while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Pipeline.getInstance().modelIdentity();
verticesData.position(positionOffset);
glVertexAttribPointer(Pipeline.getInstance().getPositionLocation(), positionSize, false, strideBytes, verticesData);
glEnableVertexAttribArray(Pipeline.getInstance().getPositionLocation());
verticesData.position(colorOffset);
glVertexAttribPointer(Pipeline.getInstance().getColorLocation(), colorSize, false, strideBytes, verticesData);
glEnableVertexAttribArray(Pipeline.getInstance().getColorLocation());
Pipeline.getInstance().updateShaders();
glDrawArrays(GL_TRIANGLES, 0, 3);
Display.update();
Display.sync(60);
}
Display.destroy();
System.exit(0);
}
private void initOpenGL(){
glViewport(0, 0, 640, 480);
glEnable(GL_DEPTH_TEST);
//Triangle
verticesData = BufferUtils.createFloatBuffer(21);
verticesData.put(new float[]{
-2.5f, -2.5f, -10,
1, 0, 0, 1,
2.5f, -2.5f, -10,
0, 1, 0, 1,
0, 2.5f, -10,
0, 0, 1, 1
}).position(0);
new Pipeline();
Pipeline.getInstance().setPerspective(45, 640.0f / 480.0f, 0.1f, 500.0f);
Pipeline.getInstance().updateShaders();
}
public static void main(String[] args){
new Main();
}
}
public class Pipeline {
private static Pipeline INSTANCE;
private int program;
private int MVPMatrixLocation;
private int positionLocation;
private int colorLocation;
private Matrix4f view;
private Matrix4f model;
private Matrix4f projection;
private FloatBuffer viewBuffer;
private FloatBuffer modelBuffer;
private FloatBuffer projectionBuffer;
private FloatBuffer MVPBuffer;
public Pipeline(){
INSTANCE = this;
loadShaders();
view = new Matrix4f();
model = new Matrix4f();
projection = new Matrix4f();
viewBuffer = BufferUtils.createFloatBuffer(16);
modelBuffer = BufferUtils.createFloatBuffer(16);
projectionBuffer = BufferUtils.createFloatBuffer(16);
MVPBuffer = BufferUtils.createFloatBuffer(16);
}
private void loadShaders(){
int vertexShaderHandle = createShader(GL_VERTEX_SHADER, ShaderUtils.loadFile("vertex.vert"));
int fragmentShaderHandle = createShader(GL_FRAGMENT_SHADER, ShaderUtils.loadFile("fragment.frag"));
int program = glCreateProgram();
if(program == 0) throw new RuntimeException("Error creating program.");
glAttachShader(program, vertexShaderHandle);
glAttachShader(program, fragmentShaderHandle);
glBindAttribLocation(program, 0, "a_Position");
glBindAttribLocation(program, 1, "a_Color");
glLinkProgram(program);
final int linkStatus = glGetProgrami(program, GL_LINK_STATUS);
if(linkStatus == 0){
glDeleteProgram(program);
throw new RuntimeException("Error linking program.");
}
MVPMatrixLocation = glGetUniformLocation(program, "MVPMatrix");
positionLocation = glGetAttribLocation(program, "a_Position");
colorLocation = glGetAttribLocation(program, "a_Color");
glUseProgram(program);
}
private int createShader(int type, String code){
int shaderHandle = glCreateShader(type);
if(shaderHandle == 0) throw new RuntimeException("Error creating "+(type==GL_VERTEX_SHADER?"vertex":"fragment")+" shader.");
glShaderSource(shaderHandle, code);
glCompileShader(shaderHandle);
final int compileStatus = glGetShaderi(shaderHandle, GL_COMPILE_STATUS);
if(compileStatus == 0){
glDeleteShader(shaderHandle);
throw new RuntimeException("Error compiling "+(type==GL_VERTEX_SHADER?"vertex":"fragment")+" shader.");
}
return shaderHandle;
}
public void updateShaders(){
MVPBuffer.clear();
calculateMVPMatrix().store(MVPBuffer);
glUniformMatrix4(MVPMatrixLocation, false, MVPBuffer);
//Print MVP matrix
/*Matrix4f temp = new Matrix4f();
Matrix4f.mul(projection, view, temp);
Matrix4f.mul(temp, model, temp);
FloatBuffer mvpTemp = BufferUtils.createFloatBuffer(16);
temp.store(mvpTemp);
for(int i=0; i<16; i++) System.out.print(mvpTemp.get(i) + " ");
System.out.println("\n");*/
}
private Matrix4f calculateMVPMatrix(){
Matrix4f result = new Matrix4f();
Matrix4f.mul(projection, model, result);
Matrix4f.mul(result, view, result);
return result;
}
/** PROJECTION MATRIX */
public void setPerspective(float fovy, float aspect, float near, float far){
/*[cot(fov/2)/a 0 0 0]
[0 cot(fov/2) 0 0]
[0 0 -(f+n)/(f-n) -1]
[0 0 -(2*f*n)/(f-n) 0]
projection.m00 = (float)(1 / Math.tan(Math.toRadians(fovy / 2)) / aspect);
projection.m11 = (float)(1 / Math.tan(Math.toRadians(fovy / 2)));
projection.m22 = (float)(-(far + near) / (far - near));
projection.m23 = -1;
projection.m33 = (float)(-(2 * far * near) / (far - near));*/
/*[cot(fov/2)/a 0 0 0]
[0 cot(fov/2) 0 0]
[0 0 -f/(f-n) -1]
[0 0 -f*n/(f-n) 0]*/
projection.m00 = (float)(1 / Math.tan(Math.toRadians(fovy / 2)) / aspect);
projection.m11 = (float)(1 / Math.tan(Math.toRadians(fovy / 2)));
projection.m22 = (float)(-far / (far-near));
projection.m23 = -1;
projection.m32 = (float)(-far * near / (far - near));
projection.m33 = 0;
}
/** MODEL MATRIX */
public void modelTranslate(float x, float y, float z){
model.translate(new Vector3f(x, y, z));
}
public void modelRotate(float angle, float x, float y, float z){
model.rotate(angle, new Vector3f(x, y, z));
}
public void modelIdentity(){
model.setIdentity();
}
/** VIEW MATRIX */
public void cameraTranslate(float x, float y, float z){
view.translate(new Vector3f(x, y, z));
}
public void cameraRotate(float angle, float x, float y, float z){
view.rotate(angle, new Vector3f(x, y, z));
}
public void cameraIdentity(){
view.setIdentity();
}
public int getPositionLocation(){
return positionLocation;
}
public int getColorLocation(){
return colorLocation;
}
public static Pipeline getInstance(){
return INSTANCE;
}
}
Vertex shader:
uniform mat4 MVPMatrix;
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main()
{
v_Color = a_Color;
gl_Position = MVPMatrix * a_Position;
}
Fragment shader:
varying vec4 v_Color;
void main()
{
gl_FragColor = v_Color;
}
Now I have only black screen, but if I set projection matrix with gluPerspective and use gl_ModelViewProjectionMatrix in vertex shader instead of MVPMatrix I can see the triangle, but then is used default opengl pipeline where I want to use my own.
And there shouldn't be problem in setting up perspective, because I checked matrices differences between gluPerspective and method which I use, found somewhere in internet. Here is the results:
gluPerspective:
1.81066 0.0 0.0 0.0 0.0 2.4142134 0.0 0.0 0.0 0.0 -1.0004001 -1.0 0.0 0.0 -0.20004001 0.0
My method:
1.8106601 0.0 0.0 0.0 0.0 2.4142137 0.0 0.0 0.0 0.0 -1.0002 -1.0 0.0 0.0 -0.10002001 0.0
There is only 0.1 difference in before last number, but I think that it's not the reason why it won't show me the triangle. So maybe someone knows where did I made mistake?