为什么我的模型在LWJGL中没有使用着色器和VBO渲染任何东西

时间:2017-07-09 10:43:02

标签: java shader render lwjgl vbo

我正在开发一个简单的类似Minecraft的游戏,但我曾经使用过一些旧的着色器系统,我想开始使用现代着色器,但是我使用渲染器卡住了,屏幕上什么都没有出现......

我尝试过不同的事情:

  • glGetError()return 0
  • 我试图在片段着色器中返回vec4(1,0,1,1),但它没有工作,所以我觉得它在顶点着色器中是个错误......

那么你能帮助我找到我的错误吗?

以下是代码:https://pastebin.com/dWJQkFZu

这是我的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);
}

我的着色器:

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;
}

请帮帮我:)。

1 个答案:

答案 0 :(得分:0)

如果要开始使用现代着色器方式,则无法使用立即方法。一切都将在着色器中计算(您必须自己编写,没有opengl预定义的优点)。所以不要打电话

    glTranslate3f(x, y, z);

您必须创建自己的模型矩阵,然后将其发送到着色器,并将其应用于模型顶点的位置。 Modern OpenGL的重点是尽量减少与它的交互。而不是让CPU和GPU携手合作(GPU想要更快地运行,CPU是瓶颈),你让CPU做一些数学计算,完成后一次性推送到GPU。

虽然您的Vertex Shader已经期待Matrix,但它没有得到它,因为它在您的Java代码中缺失,您从未通过任何Matrix。

统一mat4 MVP;

大例:

顶点着色器代码:

#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);
}

片段着色器代码:

#version 330 core

in vec4 vertexColor;

out vec4 fragColor;

void main() {
    fragColor = vec4(vertexColor.xyz,1);
}

我没有看到你的Shader编译代码,但是假设它正确......(生成着色器id,将源放入着色器,编译,生成程序并将两个着色器附加到它上面)

编译完成后,你必须告诉OpenGL输出颜色的位置:

glBindFragDataLocation(program, 0, "fragColor");

当您加载模型时,您还需要切换到现代 V ertex B uffer A rray。默认情况下,VBA可以存储16个 V ertex B uffer O 对象,它可以包含您要为顶点存储的任何数据(位置) ,颜色,纹理坐标,giv'em名称如果你愿意......)

对于这个加载部分,我使用一个单独的浮点数组(后面的一个VBO)按排序顺序保存所有数据(有关如何存储数据的更多信息,请参阅https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices

在这个例子中,我只给出一个顶点3浮点数作为位置,3浮点颜色。您还需要指定 I ndex B uffer O 对象

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
};

现在你想加载数据,并指明它的位置。

// 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);
}

现在渲染:

    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);

(是的,确实已经是这样了) 除了笑话,是的,这是一堆代码,学习它,喜欢它。我们甚至没有使用Shader的任何Matrix,但那非常简单。每次你想使用UniformLocation将Matrix(以FloatBuffer的形式)推送到着色器时

// 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);

唯一的问题是,你需要一个具有你需要的所有功能的Matrix4f类......再次说明你自己的工作,没有花哨的OpenGL调用。不要气馁,那里有几个数学库(例如:https://github.com/SilverTiger/lwjgl3-tutorial/blob/master/src/silvertiger/tutorial/lwjgl/math/Matrix4f.java

相关问题