Reputation: 3
I'm working on a simple Minecraft-like game but I used to use some old shaders system and I wanted to start using modern shaders, but I got stuck using renders and nothing appears on screen...
I've tried different things:
So could you help me getting where is my error ?
Here are the codes: https://pastebin.com/dWJQkFZu
Here is my renderLoop:
public void render(){
//check for resize
if(Display.wasResized()){
glViewport(0, 0, Display.getWidth(), Display.getHeight());
guiManager.recalculate();
}
//create perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective(Camera.fov, (float)Display.getWidth()/(float)Display.getHeight(), 0.1f, 1000000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
cam.render();
world.render();
skybox.render(cam.player.position);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
if(Camera.debug){
FontManager.getDefaultFont().drawString(0, 0, "Debug - SaintsCube v-A0.5");
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()+1, "x: "+Math.floor(player.position.x));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*2+2, "y: "+Math.floor(player.position.y));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*3+3, "z: "+Math.floor(player.position.z));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*4+4, "yaw: "+Math.floor(player.rotation.x*-1));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*5+5, "pitch: "+Math.floor(player.rotation.y));
}
guiManager.render();
glDisable(GL_ALPHA_TEST);
}
And my shaders:
chunk.vs:
#version 330
in vec3 position;
in vec2 texcoord;
in vec4 color;
uniform mat4 MVP;
out vec2 pass_texcoord;
out vec4 pass_color;
void main() {
pass_texcoord = texcoord;
pass_color = color;
gl_Position = MVP * vec4(position, 1.0);
}
chunk.fs:
#version 330
out vec4 fragcolor;
uniform sampler2D sampler;
in vec2 pass_texcoord;
in vec4 pass_color;
void main() {
vec4 texturecolor = texture(sampler, pass_texcoord) * pass_color;
if(texturecolor.a <= 0.5){
discard;
}
fragcolor = texturecolor;
}
Please help me :)
Upvotes: 0
Views: 456
Reputation: 71
If you want to start using the modern shader way, you can't use immediate methods. Everything will be calculated in the shader ( which you have to write yourself, no opengl predefined goodness ). So instead of calling
glTranslate3f(x, y, z);
you'll have to create your own Model Matrix which gets send to the shader, where it is applied to the position of the models vertices. The whole point of Modern OpenGL is to minimize the Interaction with it. Instead of having CPU and GPU work hand in hand ( GPU wants to run faster, CPU is bottlenecking ), you let the CPU do some math, and when done push it to the GPU in one go.
Whilst your Vertex Shader was already expecting the Matrix, it didnt get it because it was missing in your Java code, you never passed any Matrix.
uniform mat4 MVP;
Vertex Shader Code:
#version 330 core
in vec4 position;
in vec4 color;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec4 vertexColor;
void main() {
// Just pass the color down to the fragment shader
vertexColor = color;
// Calculate the Model, View, Projection matrix into one ( in this order, right to left )
mat4 mvp = projection * view * model;
// Calculate the position of the vertex
gl_Position = mvp * vec4(position.xyz,1);
}
Fragment Shader Code:
#version 330 core
in vec4 vertexColor;
out vec4 fragColor;
void main() {
fragColor = vec4(vertexColor.xyz,1);
}
I haven't seen your Shader compiling code, but ill assume its right... ( Generate Shader id's, put source into shaders, compile, generate program and attach both shaders to it )
After compilation you'll have to tell OpenGL where the output color goes:
glBindFragDataLocation(program, 0, "fragColor");
When you load your model's, you'll also want to switch to modern Vertex Buffer Array's. By default a VBA can store 16 Vertex Buffer Object's which can contain pretty much any data you want to store for a vertex ( position, color, texture coordinate, giv'em names if you so desire... )
For this loading part, i use one single float array ( later one VBO ) holding all data in sorted order ( see https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices for more info on how to store your data )
In this example i will only give a vertex 3 floats for position, and 3 floats for color. You'll also need to specify an Index Buffer Object
float[] data = {
// x, y, z, r, g, b
-1f, 1f, 0f, 1f, 0f, 0f,// Left top , red , ID: 0
-1f, -1f, 0f, 0f, 1f, 0f,// Left bottom, blue , ID: 1
1f, -1f, 0f, 0f, 0f, 1f,// Right bottom, green, ID: 2
1f, 1f, 0f, 1f, 1f, 1f // Right left , white, ID: 3
};
byte[] indices = {
0, 1, 2,// Left bottom triangle
2, 3, 0 // Right top triangle
};
Now you'll wanna load the data, and specify where what is.
// You have to use LWJGL3's way of memory management which is off-heap
// more info: https://blog.lwjgl.org/memory-management-in-lwjgl-3/
try(MemoryStack stack = MemoryStack.stackPush()){
FloatBuffer dataBuffer = stack.mallocFloat(data.length);
dataBuffer.put(data);
dataBuffer.flip();
indicesCount = indices.length; // Store for later use ( needed for rendering )
ByteBuffer indicesBuffer = stack.malloc(indicesCount);
indicesBuffer.put(indices);
indicesBuffer.flip();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
// Vectors
int program_in_position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(program_in_position);
glVertexAttribPointer(program_in_position, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), alreadyTakenBytes);
// Colors
int colorAttPos= glGetAttribLocation(program, "color");
glEnableVertexAttribArray(colorAttPos);
glVertexAttribPointer(colorAttPos, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), 3*(Float.SIZE / Byte.SIZE));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Now the Index VBO
indexVBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Now for rendering:
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
( Yes thats really already it ) Jokes aside, yes thats a bunch of code, learn it, love it. And we haven't even used any Matrix with the Shader, but thats really simple. Everytime you want to push a Matrix ( in form of a FloatBuffer ) to the Shader, using the UniformLocation
// This needs to happen only ONCE ( position stays the same )
int uniModel = glGetUniformLocation(program, "model");
// Create a Matrix
Matrix4f model = Matrix4f.translate(0, 0, -10);
// Create Float Buffer from Matrix4f
FloatBuffer fb = model.toBuffer();
// Push FloatBuffer to Shader
glUniformMatrix4fv(uniModel, false, fb);
The only problem there is, you'll need a Matrix4f Class with all the functions you need... and once again thats your own work, no fancy OpenGL calls. Dont be discouraged tho, there are several Math Libraries out there ( Example: https://github.com/SilverTiger/lwjgl3-tutorial/blob/master/src/silvertiger/tutorial/lwjgl/math/Matrix4f.java )
Upvotes: 1