Java LWJGL OPENGL试图渲染.obj文件但没有成功

时间:2014-04-26 00:01:38

标签: java opengl shader lwjgl .obj

我正在尝试渲染一个兔子的3D模型。

我尝试渲染.obj文件但屏幕上没有显示任何内容,这是代码:

MainDisplay类:

Code:

package com.dryadengine.gui;

import com.dryadengine.core.Model;
import com.dryadengine.framework.OBJLoader;
import com.dryadengine.framework.ShaderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;

/**
 *
 * @author Roy
 */
public class MainDisplay {

private Model bunny;
private Matrix4f mProjection;
private Matrix4f mView;
private Matrix4f mModel;
private int shaderProgramID;
private int vboID;
private int vPositionID;
private int mProjectionID;
private int mViewID;
private int mModelID;

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    MainDisplay md = new MainDisplay();
    md.create();
    md.init();
    md.run();
}

public MainDisplay() {

}

public void create() {
    try {
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.setTitle("Dryad Engine 1.0.0");
        Display.setFullscreen(false);
        Display.setResizable(true);
        Display.create();
    } catch (LWJGLException ex) {
        Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
        System.exit(-1);
    }
}

public void init() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    try {
        shaderProgramID = ShaderFactory.createShaderProgram("vertexShader", "fragmentShader");
        glUseProgram(shaderProgramID);
        bunny = OBJLoader.parseOBJ(new File("src/com/dryadengine/assets/bunny.obj"));
        FloatBuffer vbo = BufferUtils.createFloatBuffer(bunny.getVertices().length);
        vbo.put(bunny.getVertices());
        vbo.flip();
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
        vPositionID = glGetAttribLocation(shaderProgramID, "vPosition");
        glEnableVertexAttribArray(vPositionID);
        mProjection = new Matrix4f();
        float fieldOfView = 60f;
        float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
        float nearPlane = 0.1f;
        float farPlane = 100f;
        float yScale = (float)(1.0f / Math.tan((fieldOfView / 2.0f) * Math.PI / 180));//this.coTangent(this.degreesToRadians(fieldOfView / 2f));
        float xScale = yScale / aspectRatio;
        float frustum_length = farPlane - nearPlane;
        mProjection.m00 = xScale;
        mProjection.m11 = yScale;
        mProjection.m22 = -((farPlane + nearPlane) / frustum_length);
        mProjection.m23 = -1;
        mProjection.m32 = -((2 * nearPlane * farPlane) / frustum_length);
        mProjection.m33 = 0;
        mView = new Matrix4f();
        mView.m23 = -5;
        mModel = new Matrix4f();
        mProjectionID = glGetUniformLocation(shaderProgramID, "mProjection");
        mViewID = glGetUniformLocation(shaderProgramID, "mView");
        mModelID = glGetUniformLocation(shaderProgramID, "mModel");
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
        glEnable(GL_DEPTH_TEST);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
    }
}



public void run() {
    while (!Display.isCloseRequested()) {
        if (Display.isVisible()) {
            render();
        }
        if (Display.wasResized()) {
            reshape();
        }
        Display.update();
        Display.sync(60);
    }
    destroy();
}

public void render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    FloatBuffer fb1 = BufferUtils.createFloatBuffer(16);
    FloatBuffer fb2 = BufferUtils.createFloatBuffer(16);;
    FloatBuffer fb3 = BufferUtils.createFloatBuffer(16);;
    mProjection.store(fb1);
    mView.store(fb2);
    mModel.store(fb3);
    glUniformMatrix4(mProjectionID, true, fb1);
    glUniformMatrix4(mViewID, true, fb2);
    glUniformMatrix4(mModelID, true, fb3);
    for (int i = 0; i < bunny.getVertices().length / 3; i += 3) {
        glVertexAttribPointer(vPositionID, 3, GL_FLOAT, false, 0, i);
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
}

public void reshape() {
    glViewport(0, 0, Display.getWidth(), Display.getHeight());
}

public void dispose() {
    glDeleteProgram(shaderProgramID);
    glUseProgram(0);
    glDeleteBuffers(vboID);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void destroy() {
    Display.destroy();
}
}

ShaderFactory类:

package com.dryadengine.framework;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;

/**
 *
 * @author Roy
 */
public class ShaderFactory {

private static final String COMMON_SHADERS_PATH = "/com/dryadengine/shaders/";
private static final String SHADER_EXTENSION = ".dsf";

/**
 * 
 * @param vertexShaderName
 * @param fragmentShaderName
 * @return a shader program
 * @throws FileNotFoundException
 * @throws IOException 
 */
public static int createShaderProgram(String vertexShaderName, String fragmentShaderName) throws FileNotFoundException, IOException {
    ArrayList<Integer> shaders = new ArrayList();
    shaders.add(ShaderFactory.compileShader(GL_VERTEX_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + vertexShaderName + SHADER_EXTENSION)));
    shaders.add(ShaderFactory.compileShader(GL_FRAGMENT_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + fragmentShaderName + SHADER_EXTENSION)));
    return ShaderFactory.linkProgram(shaders);
}

/**
 * 
 * @param shaderFilePath
 * @return a shader file code
 * @throws FileNotFoundException
 * @throws IOException 
 */
private static String getShaderFileCode(String shaderFilePath) throws FileNotFoundException, IOException {
    StringBuilder shaderCode = new StringBuilder();
    String line;
    try {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(ShaderFactory.class.getResourceAsStream(shaderFilePath)))) {
            while ((line = br.readLine()) != null) {
                shaderCode.append(line).append("\n");
            }
        }
    } catch (FileNotFoundException e) {
        throw new FileNotFoundException(e.getMessage());
    }
    return shaderCode.toString();
}

/**
 * 
 * @param shaderType
 * @param shaderCode
 * @return a compiled shader file id
 */
public static int compileShader(int shaderType, String shaderCode) {
    int shaderID = glCreateShader(shaderType);
    glShaderSource(shaderID, shaderCode);
    glCompileShader(shaderID);
    int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
    if (status == GL_FALSE) {
        glDeleteShader(shaderID);
        throw new RuntimeException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
    }
    return shaderID;
}

/**
 * Link the vertex shader and the fragment shader to the shader program
 * @param shaders
 * @return a shader program
 */
public static int linkProgram(ArrayList <Integer> shaders) {
    int shaderProgramID = glCreateProgram();
    for (Integer shader : shaders) {
        glAttachShader(shaderProgramID, shader);
    }
    glLinkProgram(shaderProgramID);
    int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
    if (status == GL_FALSE) {
        glDeleteProgram(shaderProgramID);
        throw new RuntimeException(glGetShaderInfoLog(shaderProgramID, glGetProgrami(shaderProgramID, GL_INFO_LOG_LENGTH)));
    }
    for (int shader : shaders) {
        glDeleteShader(shader);
    }
    return shaderProgramID;
}

}

OBJLoader类:

package com.dryadengine.framework;

import com.dryadengine.core.Model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Roy
 */
public class OBJLoader {

/**
 * Parse .obj file and make a model from it.
 * @param f
 * @return a model object
 * @throws FileNotFoundException
 * @throws IOException 
 */
public static Model parseOBJ(File f) throws FileNotFoundException, IOException {
    BufferedReader br = new BufferedReader(new FileReader(f));
    String line;
    Model m;
    List<Float> vertices = new ArrayList<>();
    List<Float> normals = new ArrayList<>();
    while ((line = br.readLine()) != null) {
        if (line.startsWith("v")) {
            float x = Float.valueOf(line.split(" ")[1]);
            float y = Float.valueOf(line.split(" ")[2]);
            float z = Float.valueOf(line.split(" ")[3]);
            vertices.add(x);
            vertices.add(y);
            vertices.add(z);
        } else if (line.startsWith("vn")) {
            float x = Float.valueOf(line.split(" ")[1]);
            float y = Float.valueOf(line.split(" ")[2]);
            float z = Float.valueOf(line.split(" ")[3]);
            normals.add(x);
            normals.add(y);
            normals.add(z);
        }
    }
    br.close();
    float[] a = new float[vertices.size()];
    float[] b = new float[normals.size()];
    for (int i = 0; i < vertices.size(); i++) {
        a[i] = vertices.get(i);
    }
    for (int i = 0; i < normals.size(); i++) {
        b[i] = normals.get(i);
    }
    m = new Model(a, b);
    return m;
}

}

模特课:

package com.dryadengine.core;

/**
 *
 * @author Roy
 */
public class Model {

private float[] vertices;
private float[] normals;

/**
 * Construct a new model object.
 * @param vertices
 * @param normals 
 */
public Model(float[] vertices, float[] normals) {
    this.vertices = vertices;
    this.normals = normals;
}

/**
 * 
 * @return the model vertices array
 */
public float[] getVertices() {
    return vertices;
}

/**
 * 
 * @return the model normals array
 */
public float[] getNormals() {
    return normals;
}

}

顶点着色器代码:

#version 330

uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;

in vec4 vPosition;

void main()
{
    gl_Position = mProjection * mView * mModel * vPosition;
}

片段着色器代码:

#version 330

out vec4 color;

void main()
{
    color = vec4(1.0, 0.0, 0.0, 1.0);
}

结果只是黑屏

2 个答案:

答案 0 :(得分:1)

我不确定是否还有其他错误,因为我对GL没有太多经验,但我注意到在你的OBJLoader课程中,你要检查一行是否以&#39开头; v&#39;第一

    if (line.startsWith("v")) {

    } else if (line.startsWith("vn")) {

    }

这意味着如果它检测到&#39; vn&#39;那么它将由语句的第一部分处理,因为&#39; vn&#39;以&#39; v&#39;开头。声明的第二部分永远不会被执行。你可以检查&#39; vn&#39;首先,或者在&#39; v&#39;之后添加一个空格,检查&#39; v&#39;。

答案 1 :(得分:0)

你在render (...)方法中做了一些非常奇怪的事情;每个三角形发出一次绘制调用。

通过布局数据的方式,如果传递数组中的顶点数而不是设置不同的顶点指针并传递值 3 。

glVertexAttribPointer (vPositionID, 3, GL_FLOAT, false, 0, 0);
glDrawArrays          (GL_TRIANGLES, 0, bunny.getVertices ().length / 3);

您还可以通过将 true 传递给glUniformMatrix4来告知GL 转置 您的矩阵。如果转置矩阵,则需要在顶点着色器中反转矩阵乘法的顺序,以便进行适当的变换。

void main()
{
  gl_Position = vPosition * mModel * mView * mProjection;
}

这与你应该在OpenGL(列主要矩阵)中学习的所有东西背道而驰,所以不应该修改你的顶点着色器,而应该只是停止传递 true